[英]ImportError : Attempted relative import with no known parent package [duplicate]
我正在学习使用 python 进行编程,并且在从 package 中的模块导入时遇到问题。我正在使用带有 Python 3.8.2 64 位的 visual studio 代码。
.vscode
├── ecommerce
│ ├── __init__.py
│ ├── database.py
│ ├── products.py
│ └── payments
│ ├── __init__.py
│ ├── authorizenet.py
│ └── paypal.py
├── __init__.py
└── main.py
在ecommerce/products.py
文件中我有:
#products.py
from .database import Database
p = Database(3,2)
这样我就可以从 ecommerce ecommerce/database.py
文件中导入Database
class。 但我得到错误
ImportError : Attempted relative import with no known parent package
从Python 文档和实验看来,相对导入(涉及., .. 等)只有在以下情况下才有效
__name__
而不是__main__
,而且,__name__
是 pkg.module_name,即它必须从目录层次结构的上方导入(要有一个父 pkg 作为它的一部分__name__
。)要么
导入模块通过包含父 pkg 的模块语法指定为python -m pkg.module
,在这种情况下,它的__name__
仍然是__main__
,因此它作为脚本运行,但相对导入将起作用。 这里__package__
被设置并用于查找父 package 而__name__
是__main__
; 更多在这里。
[毕竟,看来__package__
和sys.path
是确定相对导入是否/如何工作的关键。 __name__
表示脚本或模块(即__main__
或module_name
)。 __package__
指示相对导入发生在 package 中的位置,并且__package__
的顶部需要在sys.path
中。]
因此,继续@AmitTendulkar 的示例,如果您从项目根目录将其作为> python main.py
或> python -m main
或> python -m ecommerce.products
ecommerce.products 运行,或者从该根目录输入交互式 python 并import main
或import ecommerce.products
products.py 中的相关导入将起作用。
但是,如果您从电子商务目录中> python products.py
或> python -m products
,或从该电子商务目录中输入交互式 python 并import products
,它们将失败。
补充一下很有帮助
print("In module products __package__, __name__ ==", __package__, __name__)
等在每个文件中进行调试。
更新:
导入的工作方式取决于sys.path
和__package__
,而不是__name__
。 从/home/jj
发出, > python sub/mod.py
__package__
一个sys.path
, /home/jj/sub
的 __package__ , None
- sys.path
中模块的绝对导入工作,相对导入失败。
> python -m sub.mod
__package__
sys.path
, /home/jj
的 __package__ , sys.path
中模块的sub
绝对导入工作,相对导入工作相对于sys.path
+ __package__
。
补充一下更有帮助
import sys
print("In module products sys.path[0], __package__ ==", sys.path[0], __package__)
等在每个文件中进行调试。
由于您使用的是 Python 3.8 版本,导入工作略有不同,但我认为这应该有效:
使用:
from database import Database
#Database is the class
或尝试:
import database.Database
最后,这个非常安全并且可能是最佳实践:
from . import Database
# The '.' (dot) means from within the same directory as this __init__.py module grab the Database class.
我在 Windows 上遇到了类似的问题,对我有帮助的是(适应你的目录):
# local imports
import sys
sys.path.append(r"C:\path\to\your\project")
from ecommerce.database import Database
考虑以下基本文件结构
├── ecommerce
│ ├── __init__.py
│ ├── database.py
| └── products.py
└── main.py
我假设您正在从项目根目录运行python main.py
这是从 Python 教程复制的文本,解释了相对导入的基本规则,
请注意,相对导入是基于当前模块的名称。 由于主模块的名称始终是
__main__
,因此用作 Python 应用程序的主模块的模块必须始终使用绝对导入。
所以下面的代码将起作用,
# main.py
import ecommerce.products
# or to use it directly
# from ecommerce.products import my_product
ecommerce.products.my_product()
你的 product.py 可能看起来像,
# ecommerce/products.py
from .database import Database
def my_product():
p = Database(3, 2)
database.py 如下所示,
# ecommerce/database.py
class Database():
def __init__(self, x, y):
self._x = x
self._y = y
print('Inside DB init')
# Rest of the methods...
你现在会得到,
> python main.py
Inside DB init
理想情况下,根目录下的__init__.py
文件不是必需的,因为 package 名称是从电子商务开始的。
也可以运行python -m ecommerce.products
命令直接调用products.py。 但这不会产生任何 output,因为我们没有调用 my_product() function(仅定义它)。
调用python ecommerce/products.py
将不起作用,因为当前模块的名称将变为__main__
而不是ecommerce
。 相对导入仅在当前 package 中使用时有效(因此在您的主脚本中您始终需要导入您的ecommerce
包)。
要允许使用相对导入,您需要“将您的代码变成一个包”。 这意味着所有1) 将__init__.py
放在代码的顶层目录中(在您的示例.vscode
)和2) 将完整(绝对)路径添加到顶层目录的父目录(即您的父目录) directory .vscode
) 到你的PYTHONPATH
和3) 将 Python 程序中的__package__
变量设置为包含__init__.py
的目录的名称,在你的例子中是“ .vscode
”。
然后您应该能够在ecommerce/products.py
中使用:
from .ecommerce.database import Database
我不确定为什么点在名称中.vscode
- 是目录名称的一部分,还是目录树中行的一部分? 如果是后者,请将.vscode
替换为上面的vscode
。
试试这个...
from ecommerce.database import Database
这看起来像是 hack,但它确实有效,这是因为错误的 package 结构
在你的情况下尝试导入
from.vs_code.ecommerce import database
现在无论你想在哪里调用 class 构造函数,都可以这样做:
database.Database()
您可以将其分配给一个变量并使用它。
据推测,您使文件“products.py”可执行,这违反了包的概念,package 不再是 package 并且相对导入不起作用。 您必须在 package 之外调用它。
这里我也不确定根目录名是否可以像“.vscode”一样以点开头。
尝试以下
from ecommerce import database
我正在学习使用 python 编程,但在从包中的模块导入时遇到问题。 我正在使用带有 Python 3.8.2 64 位的视觉工作室代码。
.vscode
├── ecommerce
│ ├── __init__.py
│ ├── database.py
│ ├── products.py
│ └── payments
│ ├── __init__.py
│ ├── authorizenet.py
│ └── paypal.py
├── __init__.py
└── main.py
在ecommerce/products.py
文件中,我有:
#products.py
from .database import Database
p = Database(3,2)
这样我就可以从ecommerce/database.py
文件中导入Database
类。 但我得到错误
ImportError : Attempted relative import with no known parent package
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.