如何从导入的库中设置脚本的 __package__?

How can I set __package__ of a script from within an imported library?

__package__ 属性可以设置为允许直接执行也是模块一部分的 python 脚本(例如使用相对导入)。没有 __package__,只能 运行 为 python3 -m parent.child.script 但有 __package__ = 'child',也可以 运行 更容易 python3 script.py.

来自 PEP 366:

When the main module is specified by its filename, then the package attribute will be set to None. To allow relative imports when the module is executed directly, boilerplate similar to the following would be needed before the first relative import statement:

if __name__ == "__main__" and __package__ is None:
    __package__ = "expected.package.name"

Note that this boilerplate is sufficient only if the top level package is already accessible via sys.path. Additional code that manipulates sys.path would be needed in order for direct execution to work without the top level package already being importable.

我正在尝试将此样板移动到每个脚本都可以导入的库中。我已经有可用于导入包的代码,生成了这个样板片段:

import pathlib, imptools
if __name__ == '__main__' and __package__ == None:
  __package__ = pathlib.Path(__file__).parent.name
  imptools.import_from_path(__package__, '..')

现在我想将其简化为以下内容,这需要为库中的脚本而不是脚本本身设置 __package__

import relative_import
relative_import.enable()

我知道如何找出调用库函数的脚本文件。这可以通过 inspect:

完成
import inspect
for info in inspect.stack():
  if info.filename == __file__:
    continue
  break
script = info.filename

剩下的唯一问题是,如何从库中设置脚本模块的 __package__

你想在这里做一些非常挑剔的事情,但这部分至少很容易。脚本模块始终为 __main__。您可以 import __main__ 并设置 __main__.__package__.

我创建了 imptools 包来轻松启用模块内脚本的相对导入:

import imptools  # pip3 install imptools

imptools.enable_relative()

# Relative imports...

该脚本可以是 运行 任何目录中的 python3 -m module.scriptpython3 script.py