我曾尝试为 Python 3 开发一个“模块扩展器”工具,但我遇到了一些问题。
想法如下:对于给定的 Python 脚本main.py,该工具expanded_main.py通过用导入模块的实际代码替换每个导入语句来生成功能等效的 Python 脚本;这假设导入的 Python 源代码是可访问的。为了以正确的方式完成这项工作,我使用了astPython的内置模块以及astor允许将 AST 转储回 Python 源代码的第三方工具。这个导入扩展器的动机是能够将脚本编译成一个单独的字节码块,因此 Python VM 不应该负责导入模块(例如,这可能对 MicroPython 有用)。
最简单的情况是以下语句:
from import my_module1 import *
Run Code Online (Sandbox Code Playgroud)
为了转换它,我的工具会查找一个文件my_module1.py,并用该文件的内容替换 import 语句。然后,expanded_main.py可以访问 中定义的任何名称my_module,就好像模块是以正常方式导入的一样。我不在乎可能揭示诀窍的微妙副作用。另外,为了简化,我把它from import my_module1 import a, b, c当作之前的导入(带星号),不关心可能的副作用。到现在为止还挺好。
现在这是我的观点。你怎么能处理这种进口的味道:
import my_module2
Run Code Online (Sandbox Code Playgroud)
我的第一个想法是通过创建一个与模块同名的类并复制缩进的 Python 文件的内容来模拟这一点:
class my_module2:
# content of my_module2.py
…
Run Code Online (Sandbox Code Playgroud)
这实际上适用于许多情况,但遗憾的是,我发现这有几个小问题:其中之一是它失败了,函数的主体引用了模块中定义的全局变量。例如,考虑以下两个 Python 文件:
# my_module2.py
g = "Hello"
def greetings():
print (g + " World!")
Run Code Online (Sandbox Code Playgroud)
和
# main.py
import my_module2
print(my_module2.g)
my_module2.greetings()
Run Code Online (Sandbox Code Playgroud)
在执行时,main.py打印"Hello"和"Hello World!". 现在,我的扩展器工具将生成:
# expanded_main.py
class my_module2:
g = "Hello"
def greetings():
print (g + " World!")
print(my_module2.g)
my_module2.greetings()
Run Code Online (Sandbox Code Playgroud)
执行时expanded_main.py,第一个打印语句是 OK ( "Hello") 但问候函数引发异常:NameError: name 'g' is not defined。实际发生的是
my_module2,g是一个全局变量,my_module2,g是一个类变量,应称为my_module2.g。当你定义功能,...在课堂上其他类似的副作用发生my_module2.py,你想指他们在其他函数,类...相同的my_module2.py。
知道如何解决这些问题吗?
除了类,是否还有其他允许模仿模块的 Python 构造?
最后一点:我知道该工具应该注意 1° 的嵌套导入(递归),2° 的同一模块可能的多次导入。我不希望在这里讨论这些话题。
您可以在函数(特别是实例方法)的范围内执行模块的源代码。然后,可以通过在相应的类上进行定义__getattr__并保留初始函数的locals(). 这是一些示例代码:
class Importer:
def __init__(self):
g = "Hello"
def greetings():
print (g + " World!")
self._attributes = locals()
def __getattr__(self, item):
return self._attributes[item]
module1 = Importer()
print(module1.g)
module1.greetings()
Run Code Online (Sandbox Code Playgroud)
嵌套导入可以通过以相同方式用 的实例替换来自然地处理Importer。重复导入也不应该成为问题。
| 归档时间: |
|
| 查看次数: |
3148 次 |
| 最近记录: |