是否使用 -m 选项执行 Python 代码[重复]

2025-01-22 08:45:00
admin
原创
92
摘要:问题描述:python 解释器有-m 一个模块选项“将库模块模块作为脚本运行”。使用这个python代码a.py:if __name__ == "__main__": print __package__ print __name__ 我测试python -m a了"...

问题描述:

python 解释器有-m 一个模块选项“将库模块模块作为脚本运行”。

使用这个python代码a.py:

if __name__ == "__main__":
    print __package__
    print __name__

我测试python -m a

"" <-- Empty String
__main__

python a.py回报

None <-- None
__main__

对我来说,这两个调用似乎是相同的,只是在使用 -m 选项调用时 package 不为 None。

有趣的是,使用,我得到的结果与使用 python 模块编译得到的 a.pycpython -m runpy a相同。python -m a

这些调用之间有什么(实际)区别?它们之间有什么优缺点吗?

此外,David Beazley 的《Python Essential Reference》将其解释为“ -m 选项将库模块作为脚本运行,该脚本在执行主脚本之前在 main 模块内执行”。这是什么意思?


解决方案 1:

当您使用-m命令行标志时,Python 将为您导入模块或包,然后将其作为脚本运行。当您不使用该-m标志时,您命名的文件将仅作为脚本运行。

当你尝试运行包时,区别很重要。以下两者有很大区别:

python foo/bar/baz.py

python -m foo.bar.baz

与后一种情况一样,foo.bar被导入并且相对导入将以foo.bar作为起点正确地工作。

演示:

$ mkdir -p test/foo/bar
$ touch test/foo/__init__.py
$ touch test/foo/bar/__init__.py
$ cat << EOF > test/foo/bar/baz.py 
> if __name__ == "__main__":
>     print __package__
>     print __name__
> 
> EOF
$ PYTHONPATH=test python test/foo/bar/baz.py 
None
__main__
$ PYTHONPATH=test python -m foo.bar.baz 
foo.bar
__main__

因此,Python 在使用-m开关时必须真正关注包。普通脚本永远不可能包,因此__package__设置为None

但是使用 运行包中的包或模块-m,现在至少存在包的可能性__package__,因此变量被设置为字符串值;在上面的演示中它被设置为'foo.bar',对于不在包内的普通模块它被设置为空字符串。

至于__main__ 模块,Python 导入正在运行的脚本就像导入常规模块一样。会创建一个新的模块对象来保存全局命名空间,并将其存储在中sys.modules['__main__']。这就是__name__变量所指的内容,它是该结构中的一个键。

对于包,您可以在里面创建一个__main__.py模块并在运行时运行该模块python -m package_name;事实上,这是包作为脚本运行的唯一方法:

$ PYTHONPATH=test python -m foo.bar
python: No module named foo.bar.__main__; 'foo.bar' is a package and cannot be directly executed
$ cp test/foo/bar/baz.py test/foo/bar/__main__.py
$ PYTHONPATH=test python -m foo.bar
foo.bar
__main__

因此,当使用 命名要运行的包时-m,Python 会查找__main__该包中包含的模块并将其作为脚本执行。然后,其名称仍设置为'__main__',模块对象仍存储在 中sys.modules['__main__']

解决方案 2:

是否使用 -m 选项执行 Python 代码

使用-m旗子。

当您有脚本时,结果几乎相同,但是当您开发包时,如果没有标志-m,如果您想运行包中的子包或模块作为程序的主要入口点,就无法使导入正常工作(相信我,我已经尝试过了。)

文档

就像-m 标志上的文档所说的那样:

在 sys.path 中搜索命名的模块并将其内容作为__main__模块执行。

与 -c 选项一样,当前目录将被添加到 sys.path 的开头。

所以

python -m pdb

大致相当于

python /usr/lib/python3.5/pdb.py

(假设您当前目录中没有名为 pdb.py 的包或脚本)

解释:

行为被设计得“故意类似于”脚本。

许多标准库模块包含在执行时以脚本形式调用的代码。一个例子是timeit 模块:

一些 Python 代码旨在作为模块运行:(我认为这个例子比命令行选项文档示例更好)

$ python -m timeit '"-".join(str(n) for n in range(100))'
10000 loops, best of 3: 40.3 usec per loop
$ python -m timeit '"-".join([str(n) for n in range(100)])'
10000 loops, best of 3: 33.4 usec per loop
$ python -m timeit '"-".join(map(str, range(100)))'
10000 loops, best of 3: 25.2 usec per loop

Python 2.4 发行说明中的​​重点内容如下:

-m 命令行选项 - python -m modulename 将在标准库中查找模块并调用它。例如,python -m pdb
相当于python /usr/lib/python2.4/pdb.py

后续问题

此外,David Beazley 的《Python Essential Reference》将其解释为“-m 选项将库模块作为脚本运行,该脚本__main__在主脚本执行之前在模块内部执行”。

这意味着您可以使用 import 语句查找的任何模块都可以作为程序的入口点运行 - 如果它有一个代码块,通常靠近末尾,带有if __name__ == '__main__':

-m无需将当前目录添加到路径中:

其他地方的评论说:

-m 选项还会将当前目录添加到 sys.path,这显然是一个安全问题(参见:预加载攻击)。此行为类似于 Windows 中的库搜索顺序(最近对其进行了强化)。遗憾的是,Python 并没有跟上潮流,没有提供一种简单的方法来禁用将 . 添加到 sys.path

好吧,这表明了可能的问题 - (在 Windows 中删除引号):

echo "import sys; print(sys.version)" > pdb.py

python -m pdb
3.5.2 |Anaconda 4.1.1 (64-bit)| (default, Jul  5 2016, 11:41:13) [MSC v.1900 64 bit (AMD64)]

使用-I标志将其锁定以适应生产环境(3.4 版中的新功能):

python -Im pdb
usage: pdb.py [-c command] ... pyfile [arg] ...
etc...

来自文档:

-I

在隔离模式下运行 Python。这也意味着 -E 和 -s。在隔离模式下,sys.path 既不包含脚本的目录,也不包含用户的站点包目录。所有 PYTHON* 环境变量也将被忽略。可以施加进一步的限制以防止用户注入恶意代码。

做什么__package__

它支持显式相对导入,但与这个问题并不特别相关 - 请参阅此处的答案:Python 中“__package__”属性的用途是什么?

解决方案 3:

使用 -m 将模块(或包)作为脚本运行的主要原因是为了简化部署,尤其是在 Windows 上。您可以在 Python 库中将脚本安装在模块通常所在的同一位置 - 而不是污染 PATH 或全局可执行目录(例如 ~/.local)(每个用户的脚本目录在 Windows 中很难找到)。

然后你只需输入 -m,Python 就会自动找到脚本。例如,python -m pip将为执行它的同一 Python 解释器实例找到正确的 pip。如果没有 -m,如果用户安装了多个 Python 版本,哪一个会是“全局”pip?

如果用户更喜欢命令行脚本的“经典”入口点,则可以轻松地将它们作为小脚本添加到 PATH 中的某个位置,或者 pip 可以在安装时使用 setup.py 中的 entry_points 参数创建这些入口点。

因此只需检查__name__ == '__main__'并忽略其他不可靠的实施细节。

相关推荐
  政府信创国产化的10大政策解读一、信创国产化的背景与意义信创国产化,即信息技术应用创新国产化,是当前中国信息技术领域的一个重要发展方向。其核心在于通过自主研发和创新,实现信息技术应用的自主可控,减少对外部技术的依赖,并规避潜在的技术制裁和风险。随着全球信息技术竞争的加剧,以及某些国家对中国在科技领域的打压,信创国产化显...
工程项目管理   2793  
  为什么项目管理通常仍然耗时且低效?您是否还在反复更新电子表格、淹没在便利贴中并参加每周更新会议?这确实是耗费时间和精力。借助软件工具的帮助,您可以一目了然地全面了解您的项目。如今,国内外有足够多优秀的项目管理软件可以帮助您掌控每个项目。什么是项目管理软件?项目管理软件是广泛行业用于项目规划、资源分配和调度的软件。它使项...
项目管理软件   1710  
  PMP(Project Management Professional),即项目管理专业人士资格认证,作为全球广泛认可的项目管理领域专业资质,近年来在国内热度持续攀升。越来越多的职场人士希望通过考取PMP证书来提升自身竞争力,拓展职业发展道路。然而,PMP考试费用相对较高,这让许多人在报考前心存疑虑:这笔费用投入是否值...
PMP报考官网   0  
  PMP(Project Management Professional)考试是项目管理领域极具含金量的认证考试,然而其考试费用相对较高,对于不少考生来说是一笔不小的开支。如何在保证备考质量和顺利通过考试的前提下,节省PMP考试费用,是众多考生关心的问题。接下来,就为大家分享5个实用技巧,帮助大家合理规划,降低考试成本。...
PMP培训机构   0  
  项目管理PMP知识体系涵盖了项目从启动到结束的全生命周期管理,为项目的成功交付提供了一套科学、系统且全面的方法和理念。在实际工作中,其应用范围极为广泛,对提升项目成功率、优化资源配置以及增强团队协作等方面都有着不可忽视的作用。项目启动阶段的应用在项目启动阶段,PMP知识体系强调明确项目的商业论证和项目初步范围。商业论证...
PMP证书   0  
热门文章
项目管理软件有哪些?
曾咪二维码

扫码咨询,免费领取项目管理大礼包!

云禅道AD
禅道项目管理软件

云端的项目管理软件

尊享禅道项目软件收费版功能

无需维护,随时随地协同办公

内置subversion和git源码管理

每天备份,随时转为私有部署

免费试用