Python导入 - 解释

时间:2014-01-06 14:28:35

标签: python python-3.x import

类似问题:Understanding A Chain of Imports in Python

注意:我正在使用Python 3.3 我在同一目录中设置了以下两个文件来解释导入到我自己,但是我仍然没有得到它正在做的事情。我理解函数和类定义是需要运行的语句。

untitled.py:

import string

class testing:
    def func(self):
        try:
            print(string.ascii_lowercase)
        except:
            print('not imported')
class second:
    x=1
print('print statement in untitled executed')

stuff.py:

from untitled import testing

try:
    t=testing()
    t.func()
except NameError:
    print('testing not imported')

try:
    print(string.ascii_uppercase)
except NameError:
    print('string not imported')

try:
    print(untitled.string.ascii_uppercase)
except NameError:
    print('string not imported in untitled')

try:
    s=second()
    print(s.x)
except NameError:
    print('second not imported')

这是我从运行stuff.py获得的输出:

print statement in untitled executed
abcdefghijklmnopqrstuvwxyz
string not imported
string not imported in untitled
second not imported

执行untitled.py中的print语句,尽管在stuff.py中导入仅指定测试类。此外,stuff.py中的字符串模块的关系是什么,因为它可以在测试类中调用,而不是从外部调用。

有人可以向我解释一下这种行为吗,“来自导入”的声明究竟做了什么(它运行的是什么)?

3 个答案:

答案 0 :(得分:2)

您可以将python模块视为命名空间。请记住,导入不包括:

  • 模块仅导入一次
  • 第一次执行顶级代码
  • 任何导入,变量,函数或类声明仅影响模块本地命名空间

假设您有一个名为foo.py的模块:

import eggs

bar = "Lets drink, it's a bar'

因此,当您在另一个模块中执行from foo import bar时,您将在当前命名空间中使bar可用。如果您执行eggs,模块foo.eggs将在import foo下可用。如果你执行from foo import *,那么eggsbar和模块命名空间中的其他所有内容也将在当前命名空间中 - 但是从不这样做,在Python中不喜欢通配符导入。

如果您执行import foo然后import eggs,则eggs的顶级代码将执行一次,模块命名空间将存储在模块缓存中:如果另一个模块导入它将从此缓存中提取信息。如果您打算使用它,那么导入它 - 无需担心多次导入多次执行顶级代码。

Python程序员非常喜欢命名空间;如果可能的话,我总是尝试使用import foo然后使用foo.bar而不是from foo import bar - 它会保持命名空间的清洁并防止名称冲突。

也就是说,导入机制是可以破解的,即使对于非python的文件,你也可以使python import语句工作。

答案 1 :(得分:1)

from语句与import在加载行为方面没有任何不同。加载模块时,始终执行顶级代码。 from只控制已加载模块的哪些部分被添加到当前作用域(第一点是最重要的):

  

from表单使用稍微复杂的过程:

     
      
  • 找到from子句中指定的模块,并在必要时初始化它;
  •   
  • 对于import子句中指定的每个标识符:   
        
    • 检查导入的模块是否具有该名称的属性
    •   
    • 如果没有,尝试导入具有该名称的子模块,然后再次检查导入的模块中的该属性
    •   
    • 如果找不到该属性,则引发ImportError。
    •   
    • 否则,对该值的引用将绑定在本地名称空间中,如果存在则使用as子句中的名称,否则使用属性名称
    •   
  •   

因此,您可以使用这个不合时宜的技巧访问部分导入from的模块的内容:

print(sys.modules['untitled'].string.ascii_uppercase)

答案 2 :(得分:0)

在你的第一个文件(untitled.py)中,当python编译器解析时(因为你在导入时调用它)这个文件它将创建2个类代码对象并执行print语句。请注意,如果从命令行运行untitled.py,它甚至会打印它。

在你的第二个文件(stuff.py)中,为了添加到@Paulo注释,你只在你的namspace中导入了测试类,所以只有那个才能从untitled.py的2个代码对象中获得。 但是如果你只是说

import untitled

你的第3个“try”语句将起作用,因为它的命名空间中没有标题。

接下来的事情。尝试导入untitled.testing:)