如何在Python中打印“__main__”的帮助说明?

JBT*_*JBT 1 python interpreter python-3.x

对于导入的模块,help(<module_name>)在解释器中调用将打印模块的描述;通常,这是一个文档字符串,但如果模块以注释开头,它将作为描述传递。在未导入的脚本中(即任何带有__name__of的脚本__main__),调用print(__doc__)将给出类似的结果——但前提是存在文档字符串;它不会像help()那样拉任何评论。

那么我如何调用help()脚本本身并获取描述,特别是如果没有正确的文档字符串而只有注释?

AKX*_*AKX 5

您可以使用该模块可用的事实sys.modules['__main__']

"""
Is this what you want?
"""
import sys

if __name__ == '__main__':
    help(sys.modules['__main__'])
Run Code Online (Sandbox Code Playgroud)

产出

Help on module __main__:

NAME
    __main__ - Is this what you want?

DATA
    __annotations__ = {}

FILE
    /Users/akx/Desktop/so61453557.py

(END)
Run Code Online (Sandbox Code Playgroud)

或者,对于没有文档字符串但有注释的文件:

# This is
# the description
# and not even a haiku

import sys

if __name__ == '__main__':
    help(sys.modules['__main__'])
Run Code Online (Sandbox Code Playgroud)
Help on module __main__:

NAME
    __main__

DESCRIPTION
    # This is
    # the description
    # and not even a haiku

DATA
    __annotations__ = {}

FILE
    /Users/akx/Desktop/so61453557.py

(END)
Run Code Online (Sandbox Code Playgroud)

编辑

好的,结果比我想象的更有趣,深入研究 CPython 内部!

python -i so61453557.pypython -m so61453557在这里采取不同的行动。

前者叫pymain_run_file(),哪个叫PyRun_AnyFileExFlags(),哪个叫PyRun_SimpleFileExFlags()。据我所知,它基本上合成了一个__main__模块并使用PyRun_FileExFlags.

后者调用pymain_run_module(),其实际逻辑包含在 stdlibrunpy.py模块 ( _run_module_as_main) 中。

在那之后,

-i设置 ( interactive, inspect) 时pymain_repl()被调用,如果设置了它可能会调用一个交互式钩子(例如 readline 完成和东西),然后调用PyRun_AnyFileFlags(stdin, "<stdin>", cf).

我不知道__main__运行文件后清理了什么(可能是XDECREF()在 末尾PyRun_SimpleFileExFlags),但这里有一些结论。

  • python -i -m so61453557似乎保留__main__( <module '__main__' from 'so61453557.py'>),因此您可以help(sys.modules['__main__'])在 REPL 中按预期运行。
  • python -i so61453557.py: 进入 REPL 时,__main__模块恢复为<module '__main__' (<_frozen_importlib_external.SourceFileLoader object at 0x10fb2e990>)>.
  • python有第三个版本__main__<module '__main__' (built-in)>

作为一名黑客,我认为可以sys.modules['hack'] = sys.modules['__main__'],但这不起作用;模块本身正在被改变,并且模块对象不能被腌制,所以你也不能分配copy.copy(main)

但是,TL;DR:如果您使用python -i -m something,这会起作用,如果您使用,则不会python -i something.py