如何在Python中打印“__main__”的帮助说明?
How Can I Print The Help Description Of "__main__" In Python?
对于引入的模块,在解释器中调用help(<module_name>)
会打印模块的描述;通常,这是一个文档字符串,但如果模块以注释开头,它会将这些作为描述传递。在未导入的脚本中(即任何带有 __main__
的 __name__
的脚本),调用 print(__doc__)
将给出类似的结果——但前提是存在文档字符串;它不会像 help()
那样提取任何评论。
那么如何在脚本本身上调用 help()
并获取描述,尤其是在没有适当的文档字符串而只有注释的情况下?
您可以使用模块可用的事实 sys.modules['__main__']
:
"""
Is this what you want?
"""
import sys
if __name__ == '__main__':
help(sys.modules['__main__'])
产出
Help on module __main__:
NAME
__main__ - Is this what you want?
DATA
__annotations__ = {}
FILE
/Users/akx/Desktop/so61453557.py
(END)
或者,对于没有文档字符串但有注释的文件:
# This is
# the description
# and not even a haiku
import sys
if __name__ == '__main__':
help(sys.modules['__main__'])
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)
编辑
好的,结果比我想象的更有趣,并且深入研究了 CPython 的内部结构!
python -i so61453557.py
和 python -m so61453557
在这里的行为不同。
前者调用pymain_run_file()
,后者调用PyRun_AnyFileExFlags()
,后者调用PyRun_SimpleFileExFlags()
。据我所知,它基本上合成了一个 __main__
模块并使用 PyRun_FileExFlags
在该上下文中评估文件。
后者调用pymain_run_module()
,其真正的逻辑包含在stdlib runpy.py
模块中(_run_module_as_main
)。
之后,
当 -i
被设置时(interactive
,inspect
),pymain_repl()
被调用,如果设置它可能会调用一个交互式挂钩(例如 readline 完成和东西) , 然后调用 PyRun_AnyFileFlags(stdin, "<stdin>", cf)
.
我不知道在文件运行之后清除了__main__
(可能是PyRun_SimpleFileExFlags
末尾的XDECREF()
),但是这里有一些结论。
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__']
,但那行不通;模块本身正在被更改,模块对象不能被 pickle,所以你也不能分配 copy.copy(main)
。
但是,TL;DR: 如果你使用 python -i -m something
这有效,如果你使用 python -i something.py
.
则无效
对于引入的模块,在解释器中调用help(<module_name>)
会打印模块的描述;通常,这是一个文档字符串,但如果模块以注释开头,它会将这些作为描述传递。在未导入的脚本中(即任何带有 __main__
的 __name__
的脚本),调用 print(__doc__)
将给出类似的结果——但前提是存在文档字符串;它不会像 help()
那样提取任何评论。
那么如何在脚本本身上调用 help()
并获取描述,尤其是在没有适当的文档字符串而只有注释的情况下?
您可以使用模块可用的事实 sys.modules['__main__']
:
"""
Is this what you want?
"""
import sys
if __name__ == '__main__':
help(sys.modules['__main__'])
产出
Help on module __main__:
NAME
__main__ - Is this what you want?
DATA
__annotations__ = {}
FILE
/Users/akx/Desktop/so61453557.py
(END)
或者,对于没有文档字符串但有注释的文件:
# This is
# the description
# and not even a haiku
import sys
if __name__ == '__main__':
help(sys.modules['__main__'])
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)
编辑
好的,结果比我想象的更有趣,并且深入研究了 CPython 的内部结构!
python -i so61453557.py
和 python -m so61453557
在这里的行为不同。
前者调用pymain_run_file()
,后者调用PyRun_AnyFileExFlags()
,后者调用PyRun_SimpleFileExFlags()
。据我所知,它基本上合成了一个 __main__
模块并使用 PyRun_FileExFlags
在该上下文中评估文件。
后者调用pymain_run_module()
,其真正的逻辑包含在stdlib runpy.py
模块中(_run_module_as_main
)。
之后,
当 -i
被设置时(interactive
,inspect
),pymain_repl()
被调用,如果设置它可能会调用一个交互式挂钩(例如 readline 完成和东西) , 然后调用 PyRun_AnyFileFlags(stdin, "<stdin>", cf)
.
我不知道在文件运行之后清除了__main__
(可能是PyRun_SimpleFileExFlags
末尾的XDECREF()
),但是这里有一些结论。
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__']
,但那行不通;模块本身正在被更改,模块对象不能被 pickle,所以你也不能分配 copy.copy(main)
。
但是,TL;DR: 如果你使用 python -i -m something
这有效,如果你使用 python -i something.py
.