【问题标题】:Python 3.X decorator returns NonePython 3.X 装饰器返回无
【发布时间】:2019-05-05 09:54:42
【问题描述】:

我有一个函数可以读取文件路径并确定其是否为本地 (S3)。如果文件在 S3 中,我创建了一个装饰器来在本地复制文件。应用装饰器时,函数不返回任何内容(无)。

from functools import wraps

def handle_s3_download(fcn):
    @wraps(fcn)
    def inner(data_fp, *args, **kwargs):
        # Handle S3 path
        if data_fp.startswith('s3://'):
            local_data_fp = os.path.join(FOLDER,
                                         os.path.basename(data_fp))
            # Copy file only if necessary.
            if not os.path.isfile(local_data_fp):
                copy_file_from_s3(data_fp, local_data_fp)
            data_fp = local_data_fp
        # Call decorated function
        fcn(data_fp, *args, **kwargs)
    return inner

# Returns None
@handle_s3_download
def load_csv(data_fp):
   data = []
   with open(data_fp, 'rb') as f:
     data = list(csv.reader(f))
   return data


def load_json(data_fp):
    data = []
    if data_fp.startswith('s3://'):
        local_data_fp = os.path.join(FOLDER,
                                     os.path.basename(data_fp))
        # Copy file only if necessary.
        if not os.path.isfile(local_data_fp):
            copy_file_from_s3(data_fp, local_data_fp)
        data_fp = local_data_fp
    with open(data_fp, 'r') as input_file:
        data = json.load(input_file)
    logging.info('Returning data...')
    return data

load_csv('s3://test/test.csv')  # Doesn't work
load_json('s3://test/test.csv')  # Works

【问题讨论】:

  • 你从来没有return 打电话给你的# Call decorated function....
  • 在您的 inner 函数中,您只是在调用修饰函数,实际上并没有返回它。在调用 fcn(...) 之前在 inner 中添加 return 语句。
  • 你检查过内部方法返回的fcn(data_fp, *args, **kwargs)结果
  • 添加return成功了,可以移步回答吗?

标签: python python-3.x python-decorators


【解决方案1】:

如果是我,我想编码如下:

from functools import wraps
from pathlib import Path


def handle_s3_download(fcn):
    @wraps(fcn)
    def inner(data_fp, *args, **kwargs):
        # Handle S3 path
        if data_fp.startswith("s3://"):
            local_data_fp = Path(FOLDER) / os.path.basename(data_fp)
            # Copy file only if necessary.
            if not local_data_fp.is_file():
                copy_file_from_s3(data_fp, str(local_data_fp))
            data_fp = str(local_data_fp)
        # Call decorated function
        return fcn(data_fp, *args, **kwargs)

    return inner


# Returns None
@handle_s3_download
def load_csv(data_fp):
    data = list(csv.reader(Path(data_fp).read_bytes()))
    return data


def load_json(data_fp):
    if data_fp.startswith("s3://"):
        local_data_fp = os.path.join(FOLDER, os.path.basename(data_fp))
        # Copy file only if necessary.
        if not os.path.isfile(local_data_fp):
            copy_file_from_s3(data_fp, local_data_fp)
        data_fp = local_data_fp
    data = json.loads(Path(data_fp).read_text())
    logging.info("Returning data...")
    return data


load_csv("s3://test/test.csv")  # Doesn't work
load_json("s3://test/test.csv")  # Works

【讨论】:

  • 谢谢,有什么理由强制 local_data_fp 的 str 值?
  • 没有。我更喜欢使用Path
猜你喜欢
  • 2020-02-10
  • 2015-11-21
  • 2014-06-27
  • 2020-12-04
  • 2016-10-20
  • 1970-01-01
  • 1970-01-01
  • 2019-02-09
  • 2018-02-07
相关资源
最近更新 更多