存在的问题是:在Windows 7、32位Python 2.7.3中,如何解决此“尝试以非软件包方式进行相对导入”消息?我在pep-0328
上构建了该软件包的精确副本:
package/
__init__.py
subpackage1/
__init__.py
moduleX.py
moduleY.py
subpackage2/
__init__.py
moduleZ.py
moduleA.py
导入是从控制台完成的。
我确实在相应的模块中创建了名为垃圾邮件和鸡蛋的函数。自然,它不起作用。答案显然是在我列出的第4个网址中,但对我来说都是校友。我访问的其中一个URL上有此响应:
相对导入使用模块的名称属性来确定该模块在包层次结构中的位置。如果模块的名称不包含任何包信息(例如,将其设置为“ main”),则相对导入的解析就好像该模块是顶级模块一样,无论该模块实际位于文件系统上的哪个位置。
上面的回答看起来很有希望,但对我来说,全是象形文字。因此,我的问题是,如何使Python不返回“未打包的相对导入尝试”?可能有一个涉及-m的答案。
有人可以告诉我为什么Python会给出该错误消息,“非包装”是什么意思,为什么以及如何定义“包装”以及准确的答案
这是一个解释。简短的版本是直接运行Python文件与从其他位置导入该文件之间存在很大差异。 仅知道文件位于哪个目录并不能确定Python认为位于哪个软件包。 此外,这还取决于你如何通过运行或导入将文件加载到Python中。
加载Python文件的方式有两种:作为顶级脚本或作为模块。如果直接执行文件(例如,通过python myfile.py
在命令行上键入),则会将文件作为顶级脚本加载。如果你这样做python -m myfile
,则将其作为模块加载,或者import在其他文件中遇到语句时将其加载。一次只能有一个顶级脚本。顶层脚本是你为了开始而运行的Python文件。
加载文件时,将为其指定一个名称(存储在其__name__属性中)。如果已将其作为顶级脚本加载,则其名称为__main__。如果将其作为模块加载,则其名称为文件名,其后是其所属的所有软件包/子软件包的名称,以点分隔。
例如,在你的示例中:
package/
__init__.py
subpackage1/
__init__.py
moduleX.py
moduleA.py
如果你导入moduleX
(请注意:imported
,未直接执行),则其名称为package.subpackage1.moduleX
。如果导入moduleA
,则名称为package.moduleA
。但是,如果直接从命令行运行 moduleX
,则名称为__main__
,如果直接从命令行运行moduleA
,则名称为__main__
。当模块作为顶级脚本运行时,它将失去其常规名称,而其名称改为__main__
。
还有一个额外的问题:模块的名称取决于它是从其所在目录“直接”导入还是通过软件包导入。仅当你在目录中运行Python并尝试在该目录(或其子目录)中导入文件时,这才有所不同。例如,如果你在目录中启动Python解释器package/subpackage1
,然后执行do import moduleX
,则其名称moduleX将仅为moduleX
,而不是package.subpackage1.moduleX
。这是因为Python在启动时会将当前目录添加到其搜索路径中。如果它在当前目录中找到了要导入的模块,则不会知道该目录是软件包的一部分,并且软件包信息也不会成为模块名称的一部分。
一种特殊情况是,如果你以交互方式运行解释器(例如,只需键入python并开始即时输入Python代码)。在这种情况下,该交互式会话的名称为__main__
。
现在,这是你的错误消息的关键所在:如果模块的名称没有点,则不认为它是包的一部分。文件实际在磁盘上的哪个位置都没有关系。重要的是它的名称是什么,它的名称取决于你如何加载它。
现在查看你在问题中包含的报价:
相对导入使用模块的名称属性来确定该模块在包层次结构中的位置。如果模块的名称不包含任何包信息(例如,将其设置为“ main
”),则相对导入的解析就好像该模块是顶级模块一样,无论该模块实际位于文件系统上的哪个位置。
相对导入使用模块的名称来确定它在包中的位置。当你使用类似的相对导入时from .. import foo
,点表示在软件包层次结构中增加了一定数量的级别。例如,如果你当前模块的名称是package.subpackage1.moduleX
,则..moduleA
表示package.moduleA
。为了使a from .. import
起作用,模块名称必须至少包含与import语句中一样多的点。
但是,如果模块的名称为__main__
,则不认为它在软件包中。它的名称没有点,因此你不能from .. import
在其中使用语句。如果你尝试这样做,则会收到“非包中的相对导入”错误。
你可能要做的是尝试从命令行运行moduleX
等。当你执行此操作时,其名称设置为__main__
,这意味着其中的相对导入将失败,因为其名称不会显示它在软件包中。请注意,如果你从模块所在的同一目录中运行Python,然后尝试导入该模块,也会发生这种情况,因为如上所述,Python
会“过早”在当前目录中找到该模块,而没有意识到它是包装的一部分。
还请记住,当你运行交互式解释器时,该交互式会话的“名称”始终为__main__。因此,你不能直接从交互式会话进行相对导入。相对导入仅在模块文件中使用。
如果你确实确实想moduleX
直接运行,但是仍然希望将其视为软件包的一部分,则可以这样做python -m package.subpackage1.moduleX
。该命令-m告诉Python将其作为模块而不是顶级脚本进行加载。
也许你实际上并不想运行 moduleX
,而只想运行其他脚本,例如myfile.py
,该脚本使用 inside
的功能moduleX
。如果是这样的话,把myfile.py
其他地方 - 没有内部package
目录-并运行它。如果myfile.py
你在内部做类似的事情from package.moduleA import spam
,它将很好地工作。
对于这两种解决方案中的任何一种,都package必须可从Python模块搜索路径(sys.path
)访问包目录(在你的示例中)。如果不是,你将根本无法可靠地使用包装中的任何物品。
从Python 2.6开始,用于程序包解析的模块的“名称”不仅由其__name__
属性确定,而且由__package__
属性确定。这就是为什么我避免使用显式符号__name__
来引用模块的“名称”的原因。因为Python 2.6模块的“名”是有效的__package__ + '.' +
__name__
,或者只是__name__
如果__package__
是None
)。
我来过这里: http://www.python.org/dev/peps/pep-0328/ http://docs.python.org/2/tutorial/modules.html#软件包 Python包:相对导入 Python相对导入示例代码不工作 python 2.5中的相对导入 Python中的相对导入 Python:禁用相对导入 还有很多我没有复制的网址,有些在SO上,有些在其他站
问题内容: 大家好-我正在用Python中的相关知识来表达自己的观点。我已经阅读了30篇文档,并在SO和其他论坛上阅读了很多帖子-似乎还是行不通。 我的目录结构目前看起来像这样 我希望expander.py和language_id.py可以访问功能模块。我运行python main.py,可以从components.expander import 和components.language_id i
问题内容: 我想从同一目录中的另一个文件导入函数。 有时它对我有用,但有时我得到: 有时它可与一起使用,但有时我也会得到: 我不了解这里的逻辑,也找不到任何解释。这看起来完全是随机的。 有人可以向我解释所有这些背后的逻辑是什么? 问题答案: 不幸的是,该模块需要位于程序包内部,有时还需要作为脚本运行。知道如何实现吗? 像这样的布局很普遍… … mymodule.py像这样… ......一个myo
我想从同一目录中的另一个文件导入一个函数。 有时使用对我有效,但有时我会得到一个: 有时它与一起工作,但有时我也会得到一个: 我不明白这里的逻辑,也找不到任何解释。这看起来完全是随机的。 谁能给我解释一下这一切背后的逻辑是什么?
问题内容: 根据python文档,自python 2.5开始支持相对导入和内部包引用。我当前正在运行Python 2.7.3。因此,我尝试在自己的程序包中实现此功能,以便将其用于更简单的导入。我很惊讶地发现它引发了SyntaxError异常,我希望有人可以帮助您找到原因。 我设置了一个测试目录进行测试: 两个__init__.py模块都为空。其他模块是: 当我尝试导入second_level模块时
本文向大家介绍快速了解Python相对导入,包括了快速了解Python相对导入的使用技巧和注意事项,需要的朋友参考一下 1、绝对导入和相对导入 绝对导入:按照sys.path顺序搜索,先主目录(sys.path中第一项''),然后PYTHONPATH环境变量、标准库路径、pth指定路径等。 相对导入:在模块所在同一个包内搜索,注意该包目录与主目录的区别。 例1:有以下目录 mod.py内容:imp