【发布时间】:2019-11-18 20:13:30
【问题描述】:
例如...给定
- 环境 (A) [在其中加载模块 (B)] 提供了一个功能,例如,“注册”
- 模块 (C) [由 (B) 导入] 提供了一组实用程序来加载/运行其他脚本/模块/等
- 模块 (D) 是那些“其他脚本”之一 - 它在其主线(最外层)范围内调用“register()”,因此 至于传达 D 的主要入口点(执行/启动 D 的服务/工作的功能)以及其他项目(包括,例如参数和适当的默认值) - 和
- 模块 (B) 提供了一个函数 (runScript(filename...)),当它被调用时 -
- a) 验证请求,
- b) 装饰“注册”,这样当 (D) 作为导入/加载的一部分被加载和执行时,“注册”的调用由装饰器处理,该装饰器捕获随后要调用的入口点,
- c) 调用 C 中的实用程序过程,该过程处理可用导入机制的细微差别,然后
- i) 加载脚本(通过导入它)[它应该执行脚本,它应该执行函数调用 register,它应该调用装饰器,它应该捕获并保存“注册”入口点],并且那么
- ii) 检索并调用保存的“注册”入口点
(A) 和 (D) 都不能修改 - 我们只能修改 B 和/或 C 中的代码。
似乎当 B.runScript(filename) 被调用时,除了包装器之外,一切都按预期工作。脚本确实被加载了[即,如果它有一个 Do 方法,它将被调用。 *1] 但是如果没有 Do 方法,注册没有捕获入口点。
对于我的误解和/或误解/实施,我提前道歉
模块 B (runScript - runScript.py):
import os
import App
def getEntryPoint(pi_registration):
def registration(*args, **kwargs):
App.plugin_EntryPoint = args[10]
return True
return registration
def runScript(filename):
global register
try:
os.stat(filename)
register = getEntryPoint(register) # apply decorator
App.Do("RunScript", { 'FileName' : filename })
except:
print "script inaccessible ("+filename+")"
模块 C(应用程序(控制/仿真...)App.py):
import sys
import os
import path
import gimp
# etc...
plugin_EntryPoint = None
def Do(procedureName, options)
# ...
if procedureName == 'RunScript':
filename = options['FileName'}
# determine import mechanisms available --
isimport = False
isimportSFL = False
isimportUtil = False
isimportable = False
try:
import imp
isimport = True
except:
pass
if not isimport:
# try alternative version's loader mechanism versions...
try:
from importlib.machinery import SourceFileLoader
isimportSFL = True
except:
pass
if not isimportSFL:
try:
import importlib.util
isimportUtil = True
except:
pass
plugin_EntryPoint = None
if isimport:
moduleD = imp.load_source("module_D", filename)
elif isimportSFL:
moduleD = SourceFileLoader("module_D", filename)
elif isimportUtil:
modspec = importlib.util.spec_from_file_location("module_D", filename)
moduleD = importlib.util.module_from_spec(spec)
spec.loader.exec_module(moduleD)
if hasattr(moduleD, 'Do')
moduleD.Do() # try conventional entry point...
elif plugin_EntryPoint is None: # try 'registered' entry point...
raise AppTerminate, "no entry point registered"
else
pluginEntryPoint(App.plugin_Args)
# ...
Module D(服务插件'moduleD.py'):
def myEntrypoint():
print "entered"
register("myName", "", "", "", "", "", "", "", [], [], myEntrypoint)
if __name__ == '__main__":
main()
环境(A): 坦率地说,因为我无法确切地看到环境 (gimpfu) 是如何设置它的,所以我只能推测手头问题的 可能 等价性:
#!/usr/bin/python
def register(name, a, b, c, d, e, f, g, h, i, entrypoint):
print "Plugin "+name+ " Entrypoint "+str(entrypoint)
import RunScript
RunScript._runScript("moduleD")
import _RunScript
【问题讨论】:
-
我承认我没有阅读整个问题,但该代码中没有装饰函数......也许你误解了“装饰”的含义?
-
我认为装饰:
register = getEntryPoint(register)仅适用于模块 B。register变量是全局,但仅在模块 B 中。如果另一个模块加载 D,它会看到原版。您可能正在修补之后。 -
@Error-SyntacticalRemorse:但这是装饰器在幕后实际工作的方式。
-
你能推导出一个最小的工作示例@ChrysG吗?我认为答案很简单,但很难克服这个问题(甚至更难测试任何东西,因为您的代码不可运行)。
-
正如您在问题中提到的那样,函数装饰只不过是为对象分配名称,例如当您执行
func = decorator(func)时,使用此范围的func名称的代码将使用修饰函数。当您使用不同的名称时更容易想象:func_decorated = decorator(func)。所有有权访问func_decorated的代码都将使用修饰版本,所有有权访问func的代码将使用未修饰版本。与func = decorator(func)的唯一区别是可能会覆盖名称func。您可以使用不同的名称进行追踪。
标签: python python-import python-decorators