在Python中导入包
我可能遗漏了一些显而易见的东西,但无论如何: 在python中导入像在Python中导入包,python,python-import,Python,Python Import,我可能遗漏了一些显而易见的东西,但无论如何: 在python中导入像os这样的包时,可以直接使用任何子模块/子包。例如,这项工作: >>> import os >>> os.path.abspath(...) 但是,我有自己的软件包,其结构如下: FooPackage/ __init__.py foo.py 在这里,同样的逻辑不起作用: >>> import FooPackage >>> FooPackage.f
os
这样的包时,可以直接使用任何子模块/子包。例如,这项工作:
>>> import os
>>> os.path.abspath(...)
但是,我有自己的软件包,其结构如下:
FooPackage/
__init__.py
foo.py
在这里,同样的逻辑不起作用:
>>> import FooPackage
>>> FooPackage.foo
AttributeError: 'module' object has no attribute 'foo'
我做错了什么?您需要导入子模块:
import FooPackage.foo
您所做的是在
FooPackage/\uuuuu init\uuuuuuuuuy.py
中查找foo
。您可以通过将import FooPackage.foo作为foo
(或from.import foo
)放在FooPackage/\uuuuuu init\uuuuuuuuuuuuuu.py
中来解决这个问题,然后Python将能够在那里找到foo
。但是我建议使用我的第一个建议。当您导入FooPackage
时,Python会在PYTHONPATH上搜索目录,直到找到名为FooPackage.py
的文件或名为FooPackage
的目录,其中包含名为\uu init\uuuuuuuuuupy
的文件。但是,找到包目录后,它不会扫描该目录并自动导入所有.py文件
这种行为有两个原因。首先,导入模块会执行Python代码,这可能需要时间、内存或产生副作用。因此,您可能希望导入a.b.c.d
,而不必导入所有大型软件包a
。由软件包设计者决定a的\uuuu init\uuuu.py
是否显式导入其模块和子包以使其始终可用,或者是否让客户端程序能够选择加载的内容
第二个是更微妙的,也是一个表演的障碍。如果没有显式的import语句(在
FooPackage/\uuuu init\uuuuuuuupy
或在客户机程序中),Python不一定知道它应该导入什么名称。在不区分大小写的文件系统(如Windows中使用的文件系统)上,这可能表示名为foo
、foo
、foo
、foo
、foo
、foo
或foo
的模块。所有这些都是有效的、不同的Python标识符,因此Python仅仅从文件中没有足够的信息来了解您的意思。因此,为了在所有系统上保持一致的行为,它需要在某个地方有一个明确的导入语句来澄清名称,即使在有完整案例信息的文件系统上也是如此。您需要从中添加。将foo
导入包中的\uuuu init\uuuu.py
文件 您可以使用import语句从库中导入包
语法:导入模块名称
通过使用blow语法,只能从包中导入特定的方法
语法:从模块名称导入函数名称
有一些重要的误解需要解决,特别是在术语方面。首先,通常,当您认为您正在用python导入一个
包
时,您实际导入的是一个模块
。当您考虑帮助您组织代码的文件系统子结构时,应该使用术语package
。但是从代码的角度来看,无论何时导入包
,Python都将其视为一个模块。所有包都是模块。并非所有模块都是软件包。具有\uuuuuuuuuuuuuuu
属性的模块被视为包
您可以检查os
是否是一个模块。要确认这一点,您可以执行以下操作:
import os
print(type(os)) # will print: <type 'module'>
案例1:\uuuu init\uuuuuuy.py是一个空文件
#FooPackage imported as a module
import FooPackage
#foo is not a name defined in `__init__.py`. Error
FooPackage.foo
#FooPackage.foo imported as a module
import FooPackage.foo
#Error, foo has not been imported. To be able to use foo like this,
#you need to do: import FooPackage.foo as foo
foo.anything
#Not error, if anything is defined inside foo.py
FooPackage.foo.anything
案例2:\uuuu init\uuuuu.py中有行import foo
:
import FooPackage
#Now this is good. `foo` is sort of considered to be an attribute of
#FooPackage
FooPackage.foo
现在,假设foo不再是
模块
,而是您在\uuu init\uuuu.py
中定义的函数
。如果执行导入FooPackage.foo,它将抛出一个错误,指出foo
不是模块。之所以可以使用os.path.func()
,是因为os.path
是特定系统路径模块的别名,以便使代码更易于移植。操作系统模块为您的系统集导入正确的路径模块sys.modules['os.path']=
。这将本质上转化为适用于Windows的ntpath.func()
,或适用于linux的posixpath.func()
。据我所知,问题不是如何导入子模块,而是为什么不导入子模块就可以访问操作系统的子模块,以及如何实现类似的功能。编辑:但是,你的答案会有用的。为什么你更喜欢你的第一个建议呢?(这个信息在已经发布的其他答案中,但是你必须仔细阅读一下。因此,我再次发布了它,作为对问题的简单回答。)最好使用\uu all\uu=[“foo”]
而不是标题“案例2”,你可能需要使用from。导入foo
而不是\uuuu init\uuuuu.py
文件中的import foo
,否则可能会导致导入错误,因为Python将import foo
视为“绝对导入”(请参见中的包内引用部分),因此无法将包作为聚合导入。您只能导入该软件包的特定模块。@dr除非软件包作者希望您这样做,并且在其\uuuu init\uuuu.py
文件中专门编写了子导入,否则您不能将软件包作为聚合导入。
FooPackage/
__init__.py
foo.py
#FooPackage imported as a module
import FooPackage
#foo is not a name defined in `__init__.py`. Error
FooPackage.foo
#FooPackage.foo imported as a module
import FooPackage.foo
#Error, foo has not been imported. To be able to use foo like this,
#you need to do: import FooPackage.foo as foo
foo.anything
#Not error, if anything is defined inside foo.py
FooPackage.foo.anything
import FooPackage
#Now this is good. `foo` is sort of considered to be an attribute of
#FooPackage
FooPackage.foo