__main__.py 是什么?

2025-01-08 08:50:00
admin
原创
134
摘要:问题描述:该__main__.py文件用于什么用途,我应该在其中放入什么样的代码,以及什么时候应该有一个?解决方案 1:通常,Python 程序通过在命令行上命名 .py 文件来运行:$ python my_program.py 您还可以创建一个包含代码的目录或 zip 文件,并包含__main__.py。然...

问题描述:

__main__.py文件用于什么用途,我应该在其中放入什么样的代码,以及什么时候应该有一个?


解决方案 1:

通常,Python 程序通过在命令行上命名 .py 文件来运行:

$ python my_program.py

您还可以创建一个包含代码的目录或 zip 文件,并包含__main__.py。然后您只需在命令行上命名目录或 zip 文件,它就会__main__.py自动执行:

$ python my_program_dir
$ python my_program.zip
# Or, if the program is accessible as a module
$ python -m my_program

您必须自行决定您的应用程序是否可以从这样的执行中受益。


请注意,__main__ 模块通常不来自__main__.py文件。它可以,但通常不会。当您运行类似 的脚本时python my_program.py,脚本将作为__main__模块而不是my_program模块运行。这也适用于以python -m my_module或以其他几种方式运行的模块。

如果您在错误消息中看到名称__main__,那并不一定意味着您应该寻找__main__.py文件。

解决方案 2:

该文件有何__main__.py用途?

创建 Python 模块时,通常会让模块main在作为程序入口点运行时执行某些功能(通常包含在函数中)。这通常通过放置在大多数 Python 文件底部的以下常见习惯用法来实现:

if __name__ == '__main__':
    # execute only if run as the entry point into the program
    main()

对于具有的 Python 包,您可以获得相同的语义__main__.py,它可能具有以下结构:

.
└── demo
    ├── __init__.py
    └── __main__.py

为了看到这一点,请将以下内容粘贴到 Python 3 shell 中:

from pathlib import Path

demo = Path.cwd() / 'demo'
demo.mkdir()

(demo / '__init__.py').write_text("""
print('demo/__init__.py executed')

def main():
    print('main() executed')
""")

(demo / '__main__.py').write_text("""
print('demo/__main__.py executed')

from demo import main

main()
""")

我们可以将 demo 视为一个包并实际导入它,它会执行其中的顶层代码__init__.py(但不是main函数):

>>> import demo
demo/__init__.py executed

当我们使用包作为程序的入口点时,我们执行中的代码__main__.py,它会导入__init__.py第一个:

$ python -m demo
demo/__init__.py executed
demo/__main__.py executed
main() executed

您可以从文档中得出这一点。文档说:

__main__— 顶层脚本环境

'__main__'是顶层代码执行的范围的名称。当从标准输入、脚本或交互式提示读取时,模块的__name__设置为相等。'__main__'

模块可以通过检查自己的来发现它是否在主范围内运行__name__,这允许在模块作为脚本或使用运行时有条件地执行模块中的代码,python -m但在导入时则不行,这是一种常见的习惯用法:

if __name__ == '__main__':
     # execute only if run as a script
     main()

对于包来说,通过包含一个
__main__.py模块可以达到同样的效果,当使用 运行模块时,模块的内容将被执行-m

压缩

您还可以将此目录(包括)压缩__main__.py为单个文件,然后从命令行运行它,如下所示 - 但请注意,压缩包不能作为入口点执行子包或子模块:

from pathlib import Path

demo = Path.cwd() / 'demo2'
demo.mkdir()

(demo / '__init__.py').write_text("""
print('demo2/__init__.py executed')

def main():
    print('main() executed')
""")

(demo / '__main__.py').write_text("""
print('demo2/__main__.py executed')

from __init__ import main

main()
""")

请注意细微的变化 - 我们从中导入main__init__不是demo2- 此压缩目录不被视为包,而是脚本目录。因此必须在没有-m标志的情况下使用它。

与该问题特别相关的是 -zipapp导致压缩目录默认执行__main__.py- 并且它首先执行,然后__init__.py

$ python -m zipapp demo2 -o demo2zip
$ python demo2zip
demo2/__main__.py executed
demo2/__init__.py executed
main() executed

再次注意,这个压缩目录不是一个包 - 您也不能导入它。

解决方案 3:

这里的一些答案暗示,给定一个包含文件的“包”目录(带有或不带有明确的__init__.py文件),__main__.py使用或不使用开关运行该目录没有区别-m

最大的区别是,如果不使用开关-m则首先将“包”目录添加到路径(即sys.path)中,然后文件正常运行,没有包语义

使用-m开关时,包语义(包括相对导入)受到尊重,并且包目录本身永远不会添加到系统路径中

这是一个非常重要的区别,不仅在于相对导入是否有效,更重要的是在于规定在系统模块意外遮蔽的情况下应该导入什么


例子:

PkgTest考虑具有以下结构的目录

:~/PkgTest$ tree
.
├── pkgname
│   ├── __main__.py
│   ├── secondtest.py
│   └── testmodule.py
└── testmodule.py

__main__.py文件包含以下内容:

:~/PkgTest$ cat pkgname/__main__.py
import os
print( "Hello from pkgname.__main__.py. I am the file", os.path.abspath( __file__ ) )
print( "I am being accessed from", os.path.abspath( os.curdir ) )
from  testmodule import main as firstmain;     firstmain()
from .secondtest import main as secondmain;    secondmain()

(其他文件的定义与打印输出类似)。

如果您不使用开关运行此命令-m,您将得到以下结果。请注意,相对导入失败,但更重要的是,请注意选择了错误的测试模块(即相对于工作目录):

:~/PkgTest$ python3 pkgname
Hello from pkgname.__main__.py. I am the file ~/PkgTest/pkgname/__main__.py
I am being accessed from ~/PkgTest
Hello from testmodule.py. I am the file ~/PkgTest/pkgname/testmodule.py
I am being accessed from ~/PkgTest
Traceback (most recent call last):
  File "/usr/lib/python3.6/runpy.py", line 193, in _run_module_as_main
    "__main__", mod_spec)
  File "/usr/lib/python3.6/runpy.py", line 85, in _run_code
    exec(code, run_globals)
  File "pkgname/__main__.py", line 10, in <module>
    from .secondtest import main as secondmain
ImportError: attempted relative import with no known parent package

而使用 -m 开关,您可以获得(希望)预期的结果:

:~/PkgTest$ python3 -m pkgname
Hello from pkgname.__main__.py. I am the file ~/PkgTest/pkgname/__main__.py
I am being accessed from ~/PkgTest
Hello from testmodule.py. I am the file ~/PkgTest/testmodule.py
I am being accessed from ~/PkgTest
Hello from secondtest.py. I am the file ~/PkgTest/pkgname/secondtest.py
I am being accessed from ~/PkgTest


注意:在我看来,-m应该避免在没有开关的情况下运行。事实上,我会更进一步说,我会executable packages以这样一种方式创建任何程序,除非通过-m开关运行,否则它们都会失败。

换句话说,我只会通过“相对导入”明确地从“包内”模块导入,假设所有其他导入都代表系统模块。如果有人试图在不使用开关的情况下运行您的包-m,相对导入语句将抛出错误,而不是默默地运行错误的模块。

解决方案 4:

您创建__main__.pyyourpackage以使其可执行为:

$ python -m yourpackage

解决方案 5:

__main__.py用于 zip 文件中的 python 程序。该__main__.py文件将在 zip 文件运行时执行。例如,如果 zip 文件如下:

test.zip
     __main__.py

并且内容__main__.py

import sys
print "hello %s" % sys.argv[1]

这样,只要我们跑,python test.zip world我们就能hello world出去。

因此,__main__.py当在 zip 文件上调用 python 时,该文件就会运行。

解决方案 6:

如果您的脚本是一个目录或 ZIP 文件而不是单个 python 文件,__main__.py则当“脚本”作为参数传递给 python 解释器时将会执行。

相关推荐
  政府信创国产化的10大政策解读一、信创国产化的背景与意义信创国产化,即信息技术应用创新国产化,是当前中国信息技术领域的一个重要发展方向。其核心在于通过自主研发和创新,实现信息技术应用的自主可控,减少对外部技术的依赖,并规避潜在的技术制裁和风险。随着全球信息技术竞争的加剧,以及某些国家对中国在科技领域的打压,信创国产化显...
工程项目管理   2974  
  为什么项目管理通常仍然耗时且低效?您是否还在反复更新电子表格、淹没在便利贴中并参加每周更新会议?这确实是耗费时间和精力。借助软件工具的帮助,您可以一目了然地全面了解您的项目。如今,国内外有足够多优秀的项目管理软件可以帮助您掌控每个项目。什么是项目管理软件?项目管理软件是广泛行业用于项目规划、资源分配和调度的软件。它使项...
项目管理软件   1836  
  PLM(产品生命周期管理)系统在企业的产品研发、生产与管理过程中扮演着至关重要的角色。然而,在实际运行中,资源冲突是经常会遇到的难题。资源冲突可能导致项目进度延迟、成本增加以及产品质量下降等一系列问题,严重影响企业的效益与竞争力。因此,如何有效应对PLM系统中的资源冲突,成为众多企业关注的焦点。接下来,我们将详细探讨5...
plm项目管理系统   47  
  敏捷项目管理与产品生命周期管理(PLM)的融合,正成为企业在复杂多变的市场环境中提升研发效率、增强竞争力的关键举措。随着技术的飞速发展和市场需求的快速更迭,传统的研发流程面临着诸多挑战,而将敏捷项目管理理念融入PLM,有望在2025年实现研发流程的深度优化,为企业创造更大的价值。理解敏捷项目管理与PLM的核心概念敏捷项...
plm项目   47  
  模块化设计在现代产品开发中扮演着至关重要的角色,它能够提升产品开发效率、降低成本、增强产品的可维护性与可扩展性。而产品生命周期管理(PLM)系统作为整合产品全生命周期信息的关键平台,对模块化设计有着强大的支持能力。随着技术的不断发展,到 2025 年,PLM 系统在支持模块化设计方面将有一系列令人瞩目的技术实践。数字化...
plm软件   48  
热门文章
项目管理软件有哪些?
曾咪二维码

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

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

云端的项目管理软件

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

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

内置subversion和git源码管理

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

免费试用