首页 > 解决方案 > 如何在带有条件参数的函数中触发正确的条件语句

问题描述

我不知道如何问我的问题。我不确定我的问题是否特定于 Airflow,特定于下面共享的代码......或者只是我遗漏了一些明显的东西。

我正在开发一个 Airflow 项目,我正在导入以下模块:

https://airflow.readthedocs.io/en/latest/_modules/airflow/providers/google/cloud/hooks/gcs.html

这是我想从此模块使用的方法的代码:

def upload(self, bucket_name: str, object_name: str, filename: Optional[str] = None,
               data: Optional[Union[str, bytes]] = None, mime_type: Optional[str] = None, gzip: bool = False,
               encoding: str = 'utf-8') -> None:
        """
        Uploads a local file or file data as string or bytes to Google Cloud Storage.

        :param bucket_name: The bucket to upload to.
        :type bucket_name: str
        :param object_name: The object name to set when uploading the file.
        :type object_name: str
        :param filename: The local file path to the file to be uploaded.
        :type filename: str
        :param data: The file's data as a string or bytes to be uploaded.
        :type data: str
        :param mime_type: The file's mime type set when uploading the file.
        :type mime_type: str
        :param gzip: Option to compress local file or file data for upload
        :type gzip: bool
        :param encoding: bytes encoding for file data if provided as string
        :type encoding: str
        """
        client = self.get_conn()
        bucket = client.bucket(bucket_name)
        blob = bucket.blob(blob_name=object_name)
        if filename and data:
            raise ValueError("'filename' and 'data' parameter provided. Please "
                             "specify a single parameter, either 'filename' for "
                             "local file uploads or 'data' for file content uploads.")
        elif filename:
            if not mime_type:
                mime_type = 'application/octet-stream'
            if gzip:
                filename_gz = filename + '.gz'

                with open(filename, 'rb') as f_in:
                    with gz.open(filename_gz, 'wb') as f_out:
                        shutil.copyfileobj(f_in, f_out)
                        filename = filename_gz

            blob.upload_from_filename(filename=filename,
                                      content_type=mime_type)
            if gzip:
                os.remove(filename)
            self.log.info('File %s uploaded to %s in %s bucket', filename, object_name, bucket_name)
        elif data:
            if not mime_type:
                mime_type = 'text/plain'
            if gzip:
                if isinstance(data, str):
                    data = bytes(data, encoding)
                out = BytesIO()
                with gz.GzipFile(fileobj=out, mode="w") as f:
                    f.write(data)
                data = out.getvalue()
            blob.upload_from_string(data,
                                    content_type=mime_type)
            self.log.info('Data stream uploaded to %s in %s bucket', object_name, bucket_name)
        else:
            raise ValueError("'filename' and 'data' parameter missing. "

                             "One is required to upload to gcs.")

这基本上是调用此方法的一行代码:

conn.upload(bucket_name, object_name, data)

问题是,即使我正在传递一个名为的变量data,我也可以看到upload_from_filename当我想调用upload_from_string.

我对 python 很陌生,但我在这里的理解是,如果我传递文件名参数,则upload_from_filename应该调用该函数。如果我传递数据参数,则upload_from_string应该调用该函数。

如果我没有传递任何东西,我会收到以下预期conn.upload(bucket_name, object_name)的错误消息。filename' and 'data' parameter missing. "

根据我上面分享的代码,如果我想“切换”到该函数,我应该如何调用上传方法upload_from_string

标签: python-3.x

解决方案


您正在传递位置参数。第三个位置参数是filename,因此当您传递三个位置参数时,第三个参数转到filename,所以conn.upload()调用upload_from_filename()

要将数据作为关键字参数传递,您应该使用

conn.upload(bucket_name, object_name, data=data)

来自https://docs.python.org/3/glossary.html

有两种说法:

  • 关键字参数:在函数调用中以标识符(例如name=)开头的参数或作为字典中的值传递的参数,以**. 例如,在以下对 complex() 的调用中,3 和 5 都是关键字参数:
    complex(real=3, imag=5)
    complex(**{'real': 3, 'imag': 5})
  • 位置参数:不是关键字参数的参数。位置参数可以出现在参数列表的开头和/或作为可迭代的元素传递*。例如,3 和 5 在以下调用中都是位置参数:
    complex(3, 5)
    complex(*(3, 5))

推荐阅读