编写带有修饰函数和导入的模块
Write Module with decorated functions and imports
我在 python 文件中有此代码:
from dec import my_decorator
import asyncio
@my_decorator
async def simple_method(bar): # , x, plc_name, var_name):
print("Henlo from simple_method\npartent:{}".format(parent))
return
@my_decorator
async def other_simple_meth(bar, value):
print("Henlo from other_simple_meth:\t Val:{}".format(value))
return
async def main():
print("Start Module-Export")
open('module_functions.py', 'a').close()
# Write all decorated functions to modue_functions.py
print("Functions in module_functions.py exported")
while True:
asyncio.sleep(2)
print("z...z...Z...")
我的目标是将所有修饰函数(包括导入依赖项)写入第二个模块文件(此处为 "module_functions.py")。我的 'module_functions.py' 文件应该如下所示:
from dec import my_decorator
import asyncio
@my_decorator
async def simple_method(bar): # , x, plc_name, var_name):
print("Henlo from simple_method\npartent:{}".format(parent))
return
@my_decorator
async def other_simple_meth(bar, value):
print("Henlo from other_simple_meth:\t Val:{}".format(value))
return
我知道如何获取函数的引用和名称,但不知道如何将函数代码(包括装饰器和所有依赖项)"copy/paste" 放入单独的文件中。这甚至可能吗?
编辑:我知道 pickle 和 dill 存在,但这可能无法实现目标。问题是,其他人可能不知道转储文件的顺序并将它们加载回去 may/will 会导致问题。同样,似乎无法再次编辑此类加载的功能。
我找到了一个(不理想,但还可以)解决我的问题的方法。
I) 查找函数、协同程序等并将其写入文件 (works):
就像@MisterMiyagi 怀疑的那样,检查模块是一个不错的选择。对于常见的东西,可以使用 inspect.getsource()
获取代码并将它们写入文件:
# List of wanted stuff
func_list = [simple_method, meth_with_input, meth_with_input_and_output, func_myself]
with open('module_functions.py', 'a') as module_file:
for func in func_list:
try:
module_file.write(inspect.getsource(func))
module_file.write("\n")
except:
print("Error :( ")
II) 但是装饰的东西呢(似乎可以)?
I) 不适用于修饰的东西,它只是被忽略而不抛出异常。好像用的是from functools import wraps
。
在许多示例中,@wraps
装饰器被添加到装饰器 class 中。这对我来说是不可能的,但有一个很好的解决方法:
@wraps(lambda: simple_method) #<---add wraps-decorator here
@my_decorator
async def simple_method(parent): # , x, plc_name, var_name):
print("Henlo from simple_method\npartent:{}".format(parent))
return
包装可以放在原来的装饰 method/class/function 上面,它看起来就像我想要的那样。现在我们可以将 simple_method
添加到 I) 的 func_list
中。
III) 进口呢?
好吧,实际读取函数的依赖关系似乎相当 tricky/impossible。我的解决方法是将所有想要的导入放入 class (sigh)。这个class可以丢进I)的func_list
写入文件。
编辑:
有一种更简洁的方法,经过一些修改后,它也可能适用于 I) 和 II)。魔法模块是ast.
我已经覆盖了以下内容:
class ImportVisitor(ast.NodeVisitor):
def __init__(self, target):
super().__init__()
self.file_target = target
"pick these special nodes via overwriting: visit_classname." \
"classnames are listed in https://docs.python.org/3.6/library/ast.html#abstract-grammar"
def visit_Import(self, node):
"Overwrite func!"
"Write all statements just with import like - import ast into file_target"
str = 'import '+', '.join(alias.name for alias in node.names)
self.file_target.write(str+"\n")
def visit_ImportFrom(self, node):
"Overwrite func!"
"Write all statements with from ... import (like - from os.path import basename) into file_tagrget"
str = 'from '+ node.module+ ' import '+', '.join(alias.name for alias in node.names)
self.file_target.write(str+"\n")
现在我可以解析我自己的脚本名称并在 module_file 中填充导入和来自...在访问此树中的所有节点时它将找到的导入:
with open('module_functions.py', 'a') as module_file:
with open(basename(__file__), "rb") as f:
tree = ast.parse(f.read(), basename(__file__))
visitor = ImportVisitor(module_file)
visitor.visit(tree)
module_file.write("\n\n")
我在 python 文件中有此代码:
from dec import my_decorator
import asyncio
@my_decorator
async def simple_method(bar): # , x, plc_name, var_name):
print("Henlo from simple_method\npartent:{}".format(parent))
return
@my_decorator
async def other_simple_meth(bar, value):
print("Henlo from other_simple_meth:\t Val:{}".format(value))
return
async def main():
print("Start Module-Export")
open('module_functions.py', 'a').close()
# Write all decorated functions to modue_functions.py
print("Functions in module_functions.py exported")
while True:
asyncio.sleep(2)
print("z...z...Z...")
我的目标是将所有修饰函数(包括导入依赖项)写入第二个模块文件(此处为 "module_functions.py")。我的 'module_functions.py' 文件应该如下所示:
from dec import my_decorator
import asyncio
@my_decorator
async def simple_method(bar): # , x, plc_name, var_name):
print("Henlo from simple_method\npartent:{}".format(parent))
return
@my_decorator
async def other_simple_meth(bar, value):
print("Henlo from other_simple_meth:\t Val:{}".format(value))
return
我知道如何获取函数的引用和名称,但不知道如何将函数代码(包括装饰器和所有依赖项)"copy/paste" 放入单独的文件中。这甚至可能吗?
编辑:我知道 pickle 和 dill 存在,但这可能无法实现目标。问题是,其他人可能不知道转储文件的顺序并将它们加载回去 may/will 会导致问题。同样,似乎无法再次编辑此类加载的功能。
我找到了一个(不理想,但还可以)解决我的问题的方法。
I) 查找函数、协同程序等并将其写入文件 (works):
就像@MisterMiyagi 怀疑的那样,检查模块是一个不错的选择。对于常见的东西,可以使用 inspect.getsource()
获取代码并将它们写入文件:
# List of wanted stuff
func_list = [simple_method, meth_with_input, meth_with_input_and_output, func_myself]
with open('module_functions.py', 'a') as module_file:
for func in func_list:
try:
module_file.write(inspect.getsource(func))
module_file.write("\n")
except:
print("Error :( ")
II) 但是装饰的东西呢(似乎可以)?
I) 不适用于修饰的东西,它只是被忽略而不抛出异常。好像用的是from functools import wraps
。
在许多示例中,@wraps
装饰器被添加到装饰器 class 中。这对我来说是不可能的,但有一个很好的解决方法:
@wraps(lambda: simple_method) #<---add wraps-decorator here
@my_decorator
async def simple_method(parent): # , x, plc_name, var_name):
print("Henlo from simple_method\npartent:{}".format(parent))
return
包装可以放在原来的装饰 method/class/function 上面,它看起来就像我想要的那样。现在我们可以将 simple_method
添加到 I) 的 func_list
中。
III) 进口呢?
好吧,实际读取函数的依赖关系似乎相当 tricky/impossible。我的解决方法是将所有想要的导入放入 class (sigh)。这个class可以丢进I)的func_list
写入文件。
编辑: 有一种更简洁的方法,经过一些修改后,它也可能适用于 I) 和 II)。魔法模块是ast.
我已经覆盖了以下内容:
class ImportVisitor(ast.NodeVisitor):
def __init__(self, target):
super().__init__()
self.file_target = target
"pick these special nodes via overwriting: visit_classname." \
"classnames are listed in https://docs.python.org/3.6/library/ast.html#abstract-grammar"
def visit_Import(self, node):
"Overwrite func!"
"Write all statements just with import like - import ast into file_target"
str = 'import '+', '.join(alias.name for alias in node.names)
self.file_target.write(str+"\n")
def visit_ImportFrom(self, node):
"Overwrite func!"
"Write all statements with from ... import (like - from os.path import basename) into file_tagrget"
str = 'from '+ node.module+ ' import '+', '.join(alias.name for alias in node.names)
self.file_target.write(str+"\n")
现在我可以解析我自己的脚本名称并在 module_file 中填充导入和来自...在访问此树中的所有节点时它将找到的导入:
with open('module_functions.py', 'a') as module_file:
with open(basename(__file__), "rb") as f:
tree = ast.parse(f.read(), basename(__file__))
visitor = ImportVisitor(module_file)
visitor.visit(tree)
module_file.write("\n\n")