栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 面试经验 > 面试问答

Python

面试问答 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

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
    )。



转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/370822.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号