当前位置: 首页 > 知识库问答 >
问题:

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

秦博延
2023-03-14

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

使用此python代码a.py:

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

我测试了python-ma以获得

"" <-- Empty String
__main__

python a.py返回

None <-- None
__main__

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

有趣的是,使用python-m runpy a,我得到了与python-ma相同的结果,其中python模块被编译为a.pyc。

这些调用之间的(实际)区别是什么?他们之间有什么利弊吗?

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

共有3个答案

商辰钊
2023-03-14

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

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

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

因此,只需检查\uuuuu name\uuuu=='\ uuuuuu main\uuuuuu',忽略其他不可靠的实现细节。

慕云
2023-03-14
匿名用户

使用-m标志。

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

如-m标志上的文档所示:

搜索系统。指定模块的路径,并将其内容作为\uuuuu main\uuu模块执行。

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

所以

python -m pdb

大致相当于

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

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

行为被制作成“故意类似于”脚本。

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

一些python代码打算作为模块运行:(我认为这个示例比命令行选项doc示例更好)

$ 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-mpdb相当于python/usr/lib/python2。4/pdb。py

另外,David Beazley的Python Essential Reference将其解释为“在执行主脚本之前,-m选项以脚本的形式运行库模块,该脚本在\uuuuuuu main\uuuuu模块内执行”。

这意味着你可以用导入语句查找的任何模块都可以作为程序的切入点运行——如果它有一个代码块,通常在接近结尾的时候,如果__name__ == '__main__:。

其他地方的评论说:

m选项还将当前目录添加到sys。路径,显然是一个安全问题(请参阅:预加载攻击)。此行为类似于Windows中的库搜索顺序(在最近被强化之前)。遗憾的是,Python没有跟上潮流,也没有提供一种简单的方法来禁用添加。对系统。路径

这说明了可能的问题(在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。路径既不包含脚本的目录,也不包含用户的站点包目录。所有PYTHON*环境变量也被忽略。可以施加进一步的限制以防止用户注入恶意代码。

它允许显式的相对导入,但是与这个问题并不特别相关——请看这里的答案:Python中“__package__”属性的目的是什么?

卢英叡
2023-03-14

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

当您尝试运行包时,这种区别很重要。这两者之间有很大的区别:

python foo/bar/baz.py

python -m foo.bar.baz

与后一种情况一样,foo。导入了条形图,相对导入将与foo一起正常工作。条形码作为起点。

演示:

$ 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__

因此,当使用-m开关时,Python实际上必须关心包。一个普通的脚本永远不可能是一个包,所以__package__被设置为

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

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

对于包,您可以在内部创建一个__main__. py模块,并在运行python-mpackage_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__']中。

 类似资料:
  • 问题内容: python解释器具有 模块 选项“将库模块 模块 作为脚本运行”。 使用此python代码a.py: 我测试了 而回报 对我来说,这两个调用似乎是相同的,只是当用-m选项调用__package__时不为None。 有趣的是,有了,我得到了与编译成a.pyc的python模块相同的东西。 这些调用之间的(实际)区别是什么?它们之间有什么利弊? 同样,David Beazley的Pyth

  • 问题内容: 为了从Java执行python脚本(具有几个命​​令行参数),我尝试使用的是以下Java代码 例如,我打算执行以下命令: 请注意,参数arg3采用参数值列表。 我面临的问题是我没有找到将值列表传递给参数arg3的方法。 如果有人可以给我一些提示以解决我的问题,我将不胜感激。 我已经进行了搜索,但是找不到适合我需要的答案,如果有人找到正确的链接,请告诉我。 最好! 问题答案: 只需将它们

  • 我在这里学习选修课的教程-https://www.geeksforgeeks.org/java-8-optional-class/其中有以下几点 我正在尝试使用检查as减少行数 但无法进一步了解其他部分 有办法吗?

  • 问题内容: 考虑到此代码,我是否可以绝对确定该块始终执行,无论它是什么? 问题答案: 是的,将在执行或代码块后调用。 唯一不会被调用的时间是: 如果你调用 如果你调用 如果JVM首先崩溃 如果JVM在或catch块中达到了无限循环(或其他不间断,不终止的语句) 操作系统是否强行终止了JVM进程;例如,在UNIX上 如果主机系统死机;例如,电源故障,硬件错误,操作系统崩溃等 如果该块将由守护程序线程

  • 问题内容: Python 3等效于什么? 问题答案: 从文档: 该模块已合并到Python 3.0中。将源转换为3.0时,2to3工具将自动适应导入。 因此,您的命令是,或者取决于您的安装,它可以是:

  • 本文向大家介绍使用PyV8在Python爬虫中执行js代码,包括了使用PyV8在Python爬虫中执行js代码的使用技巧和注意事项,需要的朋友参考一下 前言 可能很多人会觉得这是一个奇葩的需求,爬虫去好好的爬数据不就行了,解析js干嘛?吃饱了撑的? 搜索一下互联网上关于这个问题还真不少,但是大多数童鞋是因为自己的js基础太烂,要么是HTML基础烂,要么ajax基础烂,反正各方面都很烂。基础这么渣不