加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 编程开发 > Python > 正文

Python包导入混乱

发布时间:2020-12-20 13:48:14 所属栏目:Python 来源:网络整理
导读:如果我有一个目录结构,如: .└── pkg ├── A.py ├── B.py ├── C.py ├── __init__.py └── test └── script.py 其中script.py包含: import pkg.Bimport pkg.Aprint pkg.A.test() A.py: import pkg.Cdef test(): return pkg.B.test() B.p
如果我有一个目录结构,如:

.
└── pkg
    ├── A.py
    ├── B.py
    ├── C.py
    ├── __init__.py
    └── test
        └── script.py

其中script.py包含:

import pkg.B
import pkg.A

print pkg.A.test()

A.py:

import pkg.C

def test():
    return pkg.B.test()

B.py:

def test():
    return 'AAAA'

C.py:

def test3():
    return 'C.test3'

并且__init__.py为空.

如果A.py导入pkg.C,则代码可以正常工作.如果我注释掉那个导入,那么它失败了:

Traceback (most recent call last):
  File "pkg/test/script.py",line 9,in <module>
    print pkg.A.test()
  File "/Users/X/Desktop/importtest/pkg/A.py",line 4,in test
    return pkg.B.test()
NameError: global name 'pkg' is not defined

将import pkg.C更改为只导入pkg,只要在script.py中导入pkg.B,也可以正常工作.

如果我从script.py注释掉pkg.B的导入,那么如果我在A.py中导入pkg或导入pkg.C它没有什么区别,我收到一个错误:

Traceback (most recent call last):
  File "pkg/test/script.py",line 10,in test
    return pkg.B.test()
AttributeError: 'module' object has no attribute 'B'

这是我期望的行为.

所以基本的问题是,为什么pkg.B.test()可以在A.py中访问,如果pkg.B没有在那里导入,如果在script.py中导入了pkg.B而且A.py导入了其他子模块?

关于这里工作的确切机制我还有点不清楚.对于描述导入逻辑的好文章的解释或指示将是最受欢迎的.

解决方法

这个问题有点陈旧,但在遇到类似问题时我偶然发现了它.这就是我所理解的情况:

模块导入一次

我们首先需要了解的是,modules are loaded only once!这意味着,例如,如果我们有:

X.py:

import Z
import Y
blah blah

Y.py:

import Z
blah bloo

运行X.py将为我们提供以下内容:

>模块Z将在第一行加载.
>将运行模块Y(作为导入Y的结果).
>虽然导入Z是模块Y中的第一行,但模块Z是
没有再加载.

注意:无论如何,无论是否加载模块,模块的名称都会导入到当前名称空间中,使其可访问但它们都引用相同的模块对象!!

导入子模块

导入子模块(例如pkg.A)时,实际上是在加载包pkg __init__.py模块,另外还要加载A.py模块.但是你正在做的是将子模块作为属性添加到包的模块中.即:

>>> import pkg
>>> hasattr(pkg,'A')
False

重新启动Python会话后:

>>> import pkg.A
>>> hasattr(pkg,'A')
True

把碎片放在一起

因此,在执行导入pkg.B时的script.py中,将加载pkg模块,并将属性B添加到其“模块对象”中.当A.py导入pkg.C时,pkg没有加载,因为它已经加载了,而是将名称pkg导入到A.py的命名空间中,同时引用在script.py中导入的同一模块对象.因为属性B已添加到该对象(在script.py中),pkg.B.test成功,即使它在A.py中执行也是如此.

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读