在Python中导入包

发布于 2024-12-29 10:19:09 字数 432 浏览 0 评论 0原文

我可能遗漏了一些明显的东西,但无论如何:

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

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

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

FooPackage/
  __init__.py
  foo.py

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

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

我做错了什么?

I am probably missing something obvious but anyway:

When you import a package like os in Python, you can use any submodules/subpackages off the bat. For example this works:

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

However, I have my own package which is structured as follows:

FooPackage/
  __init__.py
  foo.py

and here the same logic does not work:

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

What am I doing wrong?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(6

谁把谁当真 2025-01-05 10:19:09

当您导入 FooPackage 时,Python 会搜索 PYTHONPATH 上的目录,直到找到名为 FooPackage.py 的文件或包含名为 FooPackage 的文件的目录。 __init__.py。但是,找到包目录后,它不会扫描该目录并自动导入所有 .py 文件。

这种行为有两个原因。首先,导入模块会执行 Python 代码,这可能需要时间、内存或产生副作用。因此,您可能希望导入 abcd,而不必导入整个大包 a。由包设计者决定 a 的 __init__.py 是否显式导入其模块和子包以使它们始终可用,或者是否让客户端程序能够选择加载的内容。

第二个有点微妙,也是一个令人震惊的事情。如果没有显式的 import 语句(无论是在 FooPackage/__init__.py 中还是在客户端程序中),Python 不一定知道应该将 foo.py 导入为什么名称。在不区分大小写的文件系统(例如在 Windows 中使用)上,这可能表示名为 fooFooFOO的模块fOofoOFoOFOofOO。所有这些都是有效的、不同的 Python 标识符,因此 Python 仅从文件中没有足够的信息来了解您的意思。因此,为了在所有系统上表现一致,需要在某处显式导入语句来澄清名称,即使在完整案例信息可用的文件系统上也是如此。

When you import FooPackage, Python searches the directories on PYTHONPATH until it finds a file called FooPackage.py or a directory called FooPackage containing a file called __init__.py. However, having found the package directory, it does not then scan that directory and automatically import all .py files.

There are two reasons for this behaviour. The first is that importing a module executes Python code which may take time, memory, or have side effects. So you might want to import a.b.c.d without necessarily importing all of a huge package a. It's up to the package designer to decide whether a's __init__.py explicitly imports its modules and subpackages so that they are always available, or whether or leaves the client program the ability to pick and choose what is loaded.

The second is a bit more subtle, and also a showstopper. Without an explicit import statement (either in FooPackage/__init__.py or in the client program), Python doesn't necessarily know what name it should import foo.py as. On a case insensitive file system (such as used in Windows), this could represent a module named foo, Foo, FOO, fOo, foO, FoO, FOo, or fOO. All of these are valid, distinct Python identifiers, so Python just doesn't have enough information from the file alone to know what you mean. Therefore, in order to behave consistently on all systems, it requires an explicit import statement somewhere to clarify the name, even on file systems where full case information is available.

(り薆情海 2025-01-05 10:19:09

您需要导入子模块:

import FooPackage.foo

您要做的就是在 FooPackage/__init__.py 中查找 foo。你可以通过将 import FooPackage.foo as foo (或 from . import foo)放入 FooPackage/__init__.py 来解决这个问题,然后 Python 将能够在那里找到foo。但我建议使用我的第一个建议。

You need to import the submodule:

import FooPackage.foo

What you're doing is looking for foo in FooPackage/__init__.py. You could solve it by putting import FooPackage.foo as foo (or from . import foo) in FooPackage/__init__.py, then Python will be able to find foo there. But I recommend using my first suggestion.

撩发小公举 2025-01-05 10:19:09

您需要添加 from 。将 foo 导入到包中的 __init__.py 文件中。

You need to add from . import foo to the __init__.py file in your package.

不回头走下去 2025-01-05 10:19:09

有一些重要的误解需要解决,特别是术语方面的误解。首先,通常,当您认为在 python 中导入时,您实际上导入的是一个模块。当您考虑帮助您组织代码的文件系统子结构时,您应该使用术语package。但从代码角度来看,每当您导入时,Python 都会将其视为模块。所有包都是模块。并非所有模块都是包。具有 __path__ 属性的模块被视为包。

您可以检查 os 是否是一个模块。要确认这一点,您可以执行以下操作:

import os
print(type(os)) # will print: <type 'module'>

在您的示例中,当您执行 import FooPackage 时,FooPackage 也被视为并被视为一个模块,其属性(函数、类、等)据说是在 __init__.py 中定义的。由于您的 __init__.py 为空,因此它找不到 foo

import 语句之外,您不能使用 '.' 表示法来寻址模块内部的模块。如果将 module 导入到目标父包的 __init__.py 文件中,则会发生唯一的异常。为了清楚起见,让我们在这里举一些例子:

考虑您的原始结构:

FooPackage/
  __init__.py
  foo.py

情况 1:__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

情况 2:__init__.py 有行 import foo< /code> 其中:

import FooPackage

#Now this is good. `foo` is sort of considered to be an attribute of 
#FooPackage
FooPackage.foo

现在,假设 foo 不再是一个模块,而是一个您在 __init__.py函数代码>.如果你import FooPackage.foo,它会抛出一个错误,指出foo不是一个模块。

There are some important misconceptions that need to be addressed, specifically with terminology. First, usually, when you think that you are importing a package in python, what you are actually importing is a module. You should use the term package when you are thinking in terms of file system substructure that helps you organize your code. But from the code perspective, whenever you import a package, Python treats it as a module. All packages are modules. Not all modules are packages. A module with the __path__ attribute is considered a package.

You can check that os is a module. To confirm this you can do:

import os
print(type(os)) # will print: <type 'module'>

In your example, when you do import FooPackage, FooPackage is treated and considered to be a module too, and its attributes (functions, classes, etc.) are supposedly defined in __init__.py. Since your __init__.py is empty, it cannot find foo.

Outside of import statements you cannot use '.' notation to address modules inside of modules. The only exception happens if a module is imported in the intended parent's package __init__.py file. To make it clear, let's do some examples here:

Consider your original structure:

FooPackage/
  __init__.py
  foo.py

Case 1: __init__.py is an empty file

#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

Case 2: __init__.py has line import foo in it:

import FooPackage

#Now this is good. `foo` is sort of considered to be an attribute of 
#FooPackage
FooPackage.foo

Now, suppose that foo is no longer a module, but a function that you define in __init__.py. if you do import FooPackage.foo, it will throw an error saying that foo is not a module.

三寸金莲 2025-01-05 10:19:09

您可以使用 os.path.func() 的原因是因为 os.path 是特定系统路径模块的别名,以便使代码更具可移植性。 os 模块会为您的系统集 sys.modules['os.path'] = 导入正确的路径模块。对于 Windows,这本质上会转换为 ntpath.func() ,对于 Linux,则转换为 posixpath.func()

The reason you can use os.path.func() is because os.path is an alias for your particular system's path module in order to make code more portable. The os modules imports the correct path module for your system sets sys.modules['os.path'] = <path module>. Where this would essentially translate to ntpath.func() for Windows or posixpath.func() for linux.

离笑几人歌 2025-01-05 10:19:09

您可以使用 import 语句从库中导入包。

语法:导入模块名称

     ex: import math

您可以使用blow语法仅导入包中的特定方法

语法:from module_name import function_name

     ex: from math import radians

You can import a package from library using import statement.

syntax : import module_name

     ex: import math

You can import only a specific method form a package by using blow syntax

syntax : from module_name import function_name

     ex: from math import radians
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文