我正在学习使用 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
Run Code Online (Sandbox Code Playgroud)
在ecommerce/products.py我的文件中:
.vscode
??? ecommerce
? ??? __init__.py
? ??? database.py
? ??? products.py
? ??? payments
? ??? __init__.py
? ??? authorizenet.py
? ??? paypal.py
??? __init__.py
??? main.py
Run Code Online (Sandbox Code Playgroud)
这样我就可以Database从ecommerce/database.py文件中导入类。但我得到错误
ImportError : Attempted relative import with no known parent package
Run Code Online (Sandbox Code Playgroud)
Fis*_*ode 13
由于您使用的是 Python 3.8 版本,因此导入的工作方式略有不同,但我认为这应该有效:
使用:
from database import Database
#Database is the class
Run Code Online (Sandbox Code Playgroud)
或尝试:
import database.Database
Run Code Online (Sandbox Code Playgroud)
最后,这可能是非常安全的最佳实践:
from . import Database
# The '.' (dot) means from within the same directory as this __init__.py module grab the Database class.
Run Code Online (Sandbox Code Playgroud)
考虑以下基本文件结构
\n\xe2\x94\x9c\xe2\x94\x80\xe2\x94\x80 ecommerce\n\xe2\x94\x82 \xe2\x94\x9c\xe2\x94\x80\xe2\x94\x80 __init__.py\n\xe2\x94\x82 \xe2\x94\x9c\xe2\x94\x80\xe2\x94\x80 database.py\n| \xe2\x94\x94\xe2\x94\x80\xe2\x94\x80 products.py\n\xe2\x94\x94\xe2\x94\x80\xe2\x94\x80 main.py\nRun Code Online (Sandbox Code Playgroud)\n我假设您是python main.py从项目根目录运行的。
以下是从 Python 教程复制的文本,解释了相对导入的基本规则,
\n\n\n请注意,相对导入基于当前模块的名称。由于主模块的名称始终为
\n__main__,因此用作 Python 应用程序主模块的模块必须始终使用绝对导入。
所以下面的代码可以工作,
\n# main.py\nimport ecommerce.products \n# or to use it directly \n# from ecommerce.products import my_product\n\necommerce.products.my_product()\nRun Code Online (Sandbox Code Playgroud)\n你的product.py可能看起来像,
\n# ecommerce/products.py\nfrom .database import Database\n\ndef my_product():\n p = Database(3, 2)\nRun Code Online (Sandbox Code Playgroud)\ndatabase.py 如下所示,
\n# ecommerce/database.py\n\nclass Database():\n def __init__(self, x, y):\n self._x = x\n self._y = y\n print('Inside DB init')\n\n # Rest of the methods...\nRun Code Online (Sandbox Code Playgroud)\n你现在会得到,
\n> python main.py\nInside DB init\nRun Code Online (Sandbox Code Playgroud)\n理想情况下,__init__.py不需要根目录下的文件,因为包名称是从 ecommerce 开始的。
您也可以运行python -m ecommerce.products命令直接调用products.py。但这不会产生任何输出,因为我们没有调用 my_product() 函数(仅定义它)。
调用python ecommerce/products.py将不起作用,因为当前模块的名称将变为__main__而不是ecommerce。相对导入仅在当前包中使用时才有效(因此在主脚本中您始终需要导入ecommerce包)。
从Python 文档和实验看来,相对导入(涉及 .、.. 等)仅在以下情况下才有效
__name__除了__main__,更进一步,__name__进口模块是pkg.module_name,即,它已经从上方在目录层次结构中导入(具有父PKG作为它的一部分__name__。)或者
导入模块是通过包含父 pkg as 的模块语法指定的python -m pkg.module,在这种情况下它__name__仍然是__main__,因此它作为脚本运行,但相对导入将起作用。这里__package__设置并用于查找父包 while __name__is __main__;更多在这里。
[之后,似乎所有__package__和sys.path的关键是确定是否/如何相对导入工作。__name__表示脚本或模块(即,__main__或module_name)。__package__指示相对导入发生在包中的哪个位置,并且顶部__package__需要位于sys.path.]
所以,用@AmitTendulkar的例子继续,如果您运行此作为> python main.py或> python -m main或> python -m 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__)
Run Code Online (Sandbox Code Playgroud)
等在每个文件中进行调试。
更新:
导入的工作方式取决于sys.path和__package__,而不是__name__。从/home/jj,> python sub/mod.py发出sys.path, __package__of /home/jj/sub, -工作None模块的绝对导入sys.path,相对导入失败。
> python -m sub.mod有 sys.path, __package__of /home/jj, sub- 模块的绝对导入sys.path工作,相对导入工作相对于sys.path+ __package__。
添加更有帮助
import sys
print("In module products sys.path[0], __package__ ==", sys.path[0], __package__)
Run Code Online (Sandbox Code Playgroud)
等在每个文件中进行调试。
小智 7
我在 Windows 上遇到了类似的问题,对我有帮助的是(适应您的目录):
# local imports
import sys
sys.path.append(r"C:\path\to\your\project")
from ecommerce.database import Database
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
66125 次 |
| 最近记录: |