如何使用来自不同脚本的相同导入?

时间:2018-11-15 04:40:44

标签: python itertools

我有script1.py,其中有

from itertools import izip_longest, islice

script1.py中的某个地方使用了islice

我还有另一个脚本script2.py,该脚本需要在script1.py中自动执行,因为script1的输出文件是script2的输入文件。问题是,script2也需要使用islice。有没有一种方法可以使用它而无需再次在islice中导入script2

2 个答案:

答案 0 :(得分:3)

islice中使用script2的Python方法是

from itertools import islice

Python中的导入机制非常聪明。导入模块不会每次都自动加载模块。第一步始终是检查模块是否已经在sys.modules中。如果是(如您的情况),则将适当的现有引用绑定到名称空间中的名称。

让我们看一个具体的示例,其中包含以下两个模块:

mod1.py

from itertools import izip_longest, islice
from mod2 import some_function

# code that uses islice and some_function

mod2.py

from itertools import islice

def some_function():
     # do the thing

如果您运行mod1,则会发生以下(已编辑)事件序列:

  1. 创建一个空的模块对象,并根据运行脚本的方式在sys.modules['mod1']sys.modules['__main__']下注册/缓存它。
  2. 开始执行mod1.py中的代码。
  3. 检查itertools是否在sys.modules中:不是
    1. 做一些魔术来找到itertools并将其加载到sys.modules['itertools']
    2. 将属性izip_longestislice添加到不完整的mod1中的全局命名空间中
  4. 检查mod2是否在sys.modules中:不是
    1. 做些魔术来找到mod2并创建一个空的sys.modules['mod2']
    2. 开始执行mod2.py中的代码。
    3. 检查itertools中是否有sys.modules
    4. 将属性islice添加到不完整的mod2中的全局命名空间中。这基本上等同于此时进行islice = sys.modules['itertools'].islice。这里什么都没装。
    5. 执行def语句以创建一个函数对象,并将其添加到名称为mod2的{​​{1}}全局命名空间中。
    6. some_func现在已完全加载
  5. 执行mod2中的其余代码

如您所见,虽然可以说mod1模块在​​技术上被导入了两次,但仅被加载了一次。第二次,名称itertools绑定到本地名称。

您可以在这里阅读有关整个过程的官方文档:https://docs.python.org/2/reference/simple_stmts.html#the-import-statement。从至少一个版本2.0:https://docs.python.org/2.0/ref/import.html开始,此事件序列在一个实现中或另一个实现中都已存在。您可能还想在这里https://docs.python.org/2/tutorial/modules.html阅读更多有关模块工作原理的信息。通常,我发现官方文档可能是Stack Overflow之外最好的Python老师。

要记住的另一件事是模块不共享名称空间。模块内的全局变量只是该特定模块对象的属性。但是,您可能会执行以下操作:

mod2.py

islice

mod1.py

from itertools import islice

def some_function(): pass

这样,您只有一次明确导入import mod2 #use mod2.some_function and mod2.islice as attributes of mod2 。但是我不认为这是一种非常pythonic的方法。 Python的主要原则之一是“显式胜于隐式”,可读性比简洁性更重要。当您使用islice时,对读者的暗示是mod2.islice定义的函数版本不同于内置函数。

顺便说一句,考虑尽快迁移到Python 3.6+。有许多改进和新功能。不再支持Python 2.x,许多流行的第三方库(例如numpy)将在即将发布的版本中完全放弃对Python 2的支持。

答案 1 :(得分:2)

您可以在这里执行的是从script1导入*,该脚本也将包括其所有导入。像这样:

# in script2.py
from script1 import *

这样,您只需要执行一次导入。这是你的意思吗?