python -m 的 sys.argv 行为

Buc*_*uck 5 python python-import python-3.x

关于 __init__.py 在 python 3.5.2 中的行为的问题。我注意到“sys.argv”和“import __main__”的行为取决于它们的调用时间。例如:

$ tree 
??? subdir
    ??? __init__.py : "import sys; print(sys.argv)"
    ??? __main__.py : "import sys; print(sys.argv)"

$ python -m subdir
['-m']
['/path/to/code/subdir/__main__.py']
Run Code Online (Sandbox Code Playgroud)

在这里我措手不及,因为我希望 sys.argv 在整个进程生命周期中都是相同的。我对为什么会发生这种情况有一个直觉,但我想知道是否有任何方法可以在导入时知道 __init__.py 模块中真正的 sys.argv 是什么。

作为参考,看起来 Lib/runpy.py@_run_module_as_main 中的 argv 已更改

Buc*_*uck 5

简短版本:在运行之前无法找到 __main__

长版:

  • -m 标志导致 sys.argv[0] 被操纵
  • 问题在于 sys.argv 的操作时间
    • main.c@Py_main 进行一些标志解析并弹出要调用的模块名称
    • main.c@RunModule runpy.py@_run_module_as_main 的包装器
    • _run_module_as_main 设置 sys.argv[0] 但直到调用 runpy.py@_get_main_module_details 后才会这样做
      • _get_module_details 中的副作用实际上导入了包及其祖先,在 _get_main_module_details 可以解析之前执行 __init__.py 脚本,因此 _run_module_as_main 无法设置 sys.argv

我认为这可以重构,以便在 _get_module_details 导入包和祖先之前设置 sys.argv (我认为可以通过模块规范实现),但必须等待 runpy 架构的增强,可能采用以下形式截至去年年底,正在进行中。