Python 2.7 包装模块每个类的每个函数 客观的

Python 2.7 包装模块每个类的每个函数 客观的,python-2.7,Python 2.7,包装gspread模块每个类的每个函数 我知道有无数关于这个主题的帖子,大多数人都一致要求使用装饰师。 我对装饰师不太熟悉,觉得这种方法并不像我希望的那样天衣无缝。也许我没有理解正确 但是,我发现了这个“感觉”像我正在寻找的东西 (差)企图 导入gspread 从oauth2client.service\u帐户导入ServiceAccountCredentials 导入操作系统 进口检验 GoogleSheetAPI类: 定义初始化(自): f=os.path.join(os.path.dirn

包装
gspread
模块每个类的每个函数

我知道有无数关于这个主题的帖子,大多数人都一致要求使用装饰师。 我对装饰师不太熟悉,觉得这种方法并不像我希望的那样天衣无缝。也许我没有理解正确

但是,我发现了这个“感觉”像我正在寻找的东西

(差)企图
导入gspread
从oauth2client.service\u帐户导入ServiceAccountCredentials
导入操作系统
进口检验
GoogleSheetAPI类:
定义初始化(自):
f=os.path.join(os.path.dirname(_文件__),'credentials.json')
os.environ.setdefault('GOOGLE\u应用程序\u凭据',f)
范围=['https://spreadsheets.google.com/feeds',
'https://www.googleapis.com/auth/drive']
credentials=ServiceAccountCredentials.from_json_keyfile_name(f,作用域)
self.client=gspread.authorize(凭据)
self.client.login()
def安全呼叫(f):
尝试:
打印“通话前”
f()
打印“通话后”
除:
打印“捕获异常”
一无所获
对于inspect.getmembers(gspread,inspect.isclass)中的类名称c:
对于inspect.getmembers(c,inspect.ismethod)中的方法名称f:
setattr(c,f,SafeCall(f))#类型错误:属性名称必须是字符串,而不是“instancemethod”
g=谷歌表单API()
电子表格=g.client.open_by_key(“”)调用gspread.client中的函数
工作表=电子表格。get_工作表(0)#调用gspread.spreadsheet中的函数
工作表.add_行(['key','value'])#调用gspread.worksheet中的函数
笔记
  • 当我使用“无缝”这个词时,我的意思是,考虑到我的代码对许多
    gspread
    函数有许多调用,我希望尽可能少地进行更改。使用
    inspect
    /
    setattr
    似乎是一个完美/无缝的技巧

  • 实际上,您的代码有三个明显的问题

    第一个是TypeError——这很容易解决FWIW:正如错误消息(由
    setattr()
    提出)所述,“属性名称必须是字符串,而不是“instancemethod”。您确实试图使用
    f
    (方法本身)而不是
    method\u name

    setattr(c, method_name, SafeCall(f))
    
    第二个问题是,你的SafeCall“decorator”不是一个decorator。一个decorator(嗯,至少是你在这里想要的那种decorator)返回一个封装原始函数的函数,您当前的实现只调用原始函数。实际上,它几乎就是
    SafeCall
    实际应返回的函数。适当的装饰器示例如下:

    def decorator(func):
        def wrapper(*args, **kw):
            print("before calling {}".format(func))
            result = func(*args, **kw)
            print("after calling {}".format(func))
            return result
        return wrapper
    
    最后,第三个明显的问题是:

    except:
        print 'exception caught'
        return None
    
    你肯定不想要这个,这个

    1/将绝对捕获所有内容(包括
    SysExit
    ,这是Python在
    sys.exit()
    调用中提出的,以及
    StopIteration
    是迭代器发出耗尽信号的方式)

    2/放弃所有非常有用的调试信息-使其无法诊断实际出现的错误

    3/返回可能无法使用的内容,因此您必须测试每个方法调用的返回值,并且由于您不知道出现了什么问题,因此除了打印“oops,出了什么问题,但不要问我是什么、在哪里或为什么”之外,您将无法处理此问题退出程序,这肯定不比让异常传播好——在这两种情况下,程序都会崩溃,但至少如果你不理会异常,你会得到一些导致问题的提示

    4/或者,更糟糕的是,为该方法返回一个有效的返回值(是的,有很多方法被设计为更改状态并返回
    None
    ),这样您甚至不会知道发生了什么错误并愉快地继续执行-这肯定会导致错误的结果和损坏的数据

    5/更不用说,您以这种方式装饰的方法很可能相互调用,并在内部使用(预期的)异常(通过适当的异常处理),因此您实际上是在一个正常工作(或大部分正常工作)的库中引入bug

    瞧,这可能是你能想到的最糟糕的反模式

    except:
        print 'exception caught'
        return None