我可能错过了一些显而易见的东西,但无论如何:
在python中导入像os
这样的包时,可以使用任何子模块/子包。例如,这有效:
>>> import os
>>> os.path.abspath(...)
但是我有自己的包,其结构如下:
FooPackage/
__init__.py
foo.py
这里同样的逻辑不起作用:
>>> import FooPackage
>>> FooPackage.foo
AttributeError: 'module' object has no attribute 'foo'
我做错了什么?
答案 0 :(得分:61)
导入FooPackage
时,Python会搜索PYTHONPATH上的目录,直到找到名为FooPackage.py
的文件或名为FooPackage
的目录,其中包含名为__init__.py
的文件。但是,找到包目录后,它 not 然后扫描该目录并自动导入所有.py文件。
这种行为有两个原因。第一个是导入模块执行Python代码,这可能需要时间,内存或副作用。因此,您可能希望导入a.b.c.d
,而无需导入所有大型包a
。包装设计师可以决定是否__init__.py
显式地导入其模块和子包,以便它们始终可用,或者是否让客户端程序选择加载的内容。
第二个是更微妙,也是一个showstopper。如果没有显式的import语句(在FooPackage/__init__.py
或客户端程序中),Python不一定知道应该导入foo.py
的名称。在不区分大小写的文件系统(例如在Windows中使用)上,这可以表示名为foo
,Foo
,FOO
,fOo
,foO
的模块, FoO
,FOo
或fOO
。所有这些都是有效的,不同的Python标识符,因此Python只是从文件中没有足够的信息才能知道你的意思。因此,为了在所有系统上表现一致,它需要在某处明确导入语句以澄清名称,即使在可获得完整案例信息的文件系统上也是如此。
答案 1 :(得分:37)
您需要导入子模块:
import FooPackage.foo
您正在做的是在foo
中寻找FooPackage/__init__.py
。您可以通过将import FooPackage.foo as foo
(或from . import foo
)放入FooPackage/__init__.py
来解决此问题,然后Python就能在那里找到foo
。但我建议使用我的第一个建议。
答案 2 :(得分:10)
您需要将from . import foo
添加到包中的__init__.py
文件中。
答案 3 :(得分:6)
有一些重要的误解需要解决,特别是术语。首先,通常,当您认为在python中导入package
时,实际导入的是module
。在考虑帮助您组织代码的文件系统子结构时,应该使用术语package
。但是从代码的角度来看,无论何时导入package
,Python都会将其视为模块。所有包都是模块。并非所有模块都是包。具有__path__
属性的模块被视为包。
您可以检查os
是否为模块。要确认这一点,你可以这样做:
import os
print(type(os)) # will print: <type 'module'>
在您的示例中,当您执行import FooPackage
时,FooPackage
也会被视为一个模块,并且其属性(函数,类等)应该在{{1}中定义}。由于您的__init__.py
为空,因此无法找到__init__.py
。
在foo
语句之外,您不能使用import
表示法来处理模块内部的模块。如果在预期的父级包'.'
文件中导入module
,则会发生唯一的例外。为了说清楚,请在这里做一些例子:
考虑你的原始结构:
__init__.py
案例1:__ init__.py是一个空文件
FooPackage/
__init__.py
foo.py
案例2:__ init__.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 foo
现在,假设foo不再是import FooPackage
#Now this is good. `foo` is sort of considered to be an attribute of
#FooPackage
FooPackage.foo
,而是module
中定义的function
。如果您执行__init__.py
,则会发出错误消息,指出import FooPackage.foo
不是模块。
答案 4 :(得分:0)
您可以使用 os.path.func()
的原因是因为 os.path
是您特定系统路径模块的别名,以便使代码更具可移植性。 os 模块为您的系统集 sys.modules['os.path'] = <path module>
导入正确的路径模块。这基本上会转化为 ntpath.func()
(对于 Windows)或 posixpath.func()
(对于 linux)。
答案 5 :(得分:-4)
您可以使用import语句从库导入包。
语法:import module_name
ex: import math
您可以使用blow语法
仅从包中导入特定方法语法:from module_name import function_name
ex: from math import radians