用Python导入包

时间:2012-01-28 20:53:18

标签: python python-import

我可能错过了一些显而易见的东西,但无论如何:

在python中导入像os这样的包时,可以使用任何子模块/子包。例如,这有效:

>>> import os
>>> os.path.abspath(...)

但是我有自己的包,其结构如下:

FooPackage/
  __init__.py
  foo.py

这里同样的逻辑不起作用:

>>> import FooPackage
>>> FooPackage.foo
AttributeError: 'module' object has no attribute 'foo'

我做错了什么?

6 个答案:

答案 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中使用)上,这可以表示名为fooFooFOOfOofoO的模块, FoOFOofOO。所有这些都是有效的,不同的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