Python 3 中的相对导入
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/16981921/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Relative imports in Python 3
提问by John Smith Optional
I want to import a function from another file in the same directory.
我想从同一目录中的另一个文件导入一个函数。
Sometimes it works for me with from .mymodule import myfunctionbut sometimes I get a:
有时它对我有用,from .mymodule import myfunction但有时我会得到:
SystemError: Parent module '' not loaded, cannot perform relative import
Sometimes it works with from mymodule import myfunction, but sometimes I also get a:
有时它适用于from mymodule import myfunction,但有时我也会得到:
SystemError: Parent module '' not loaded, cannot perform relative import
I don't understand the logic here, and I couldn't find any explanation. This looks completely random.
我不明白这里的逻辑,我找不到任何解释。这看起来完全随机。
Could someone explain to me what's the logic behind all this?
有人可以向我解释这一切背后的逻辑吗?
采纳答案by Aya
unfortunately, this module needs to be inside the package, and it also needs to be runnable as a script, sometimes. Any idea how I could achieve that?
不幸的是,这个模块需要在包内,有时还需要作为脚本运行。知道我怎么能做到这一点吗?
It's quite common to have a layout like this...
像这样的布局很常见......
main.py
mypackage/
__init__.py
mymodule.py
myothermodule.py
...with a mymodule.pylike this...
......mymodule.py像这样......
#!/usr/bin/env python3
# Exported function
def as_int(a):
return int(a)
# Test function for module
def _test():
assert as_int('1') == 1
if __name__ == '__main__':
_test()
...a myothermodule.pylike this...
……myothermodule.py像这样……
#!/usr/bin/env python3
from .mymodule import as_int
# Exported function
def add(a, b):
return as_int(a) + as_int(b)
# Test function for module
def _test():
assert add('1', '1') == 2
if __name__ == '__main__':
_test()
...and a main.pylike this...
……还有main.py这样的……
#!/usr/bin/env python3
from mypackage.myothermodule import add
def main():
print(add('1', '1'))
if __name__ == '__main__':
main()
...which works fine when you run main.pyor mypackage/mymodule.py, but fails with mypackage/myothermodule.py, due to the relative import...
...当您运行main.pyor时效果很好mypackage/mymodule.py,但mypackage/myothermodule.py由于相对导入而失败了...
from .mymodule import as_int
The way you're supposed to run it is...
你应该运行它的方式是......
python3 -m mypackage.myothermodule
...but it's somewhat verbose, and doesn't mix well with a shebang line like #!/usr/bin/env python3.
...但它有点冗长,并且不能与像#!/usr/bin/env python3.
The simplest fix for this case, assuming the name mymoduleis globally unique, would be to avoid using relative imports, and just use...
对于这种情况,假设名称mymodule是全局唯一的,最简单的解决方法是避免使用相对导入,只需使用...
from mymodule import as_int
...although, if it's not unique, or your package structure is more complex, you'll need to include the directory containing your package directory in PYTHONPATH, and do it like this...
...虽然,如果它不是唯一的,或者你的包结构更复杂,你需要在 中包含包含你的包目录的目录PYTHONPATH,并像这样执行...
from mypackage.mymodule import as_int
...or if you want it to work "out of the box", you can frob the PYTHONPATHin code first with this...
...或者,如果您希望它“开箱即用”,您可以PYTHONPATH先使用此代码来获取代码...
import sys
import os
PACKAGE_PARENT = '..'
SCRIPT_DIR = os.path.dirname(os.path.realpath(os.path.join(os.getcwd(), os.path.expanduser(__file__))))
sys.path.append(os.path.normpath(os.path.join(SCRIPT_DIR, PACKAGE_PARENT)))
from mypackage.mymodule import as_int
It's kind of a pain, but there's a clue as to why in an emailwritten by a certain Guido van Rossum...
这有点痛苦,但在某个 Guido van Rossum 写的电子邮件中,有一个关于为什么的线索......
I'm -1 on this and on any other proposed twiddlings of the
__main__machinery. The only use case seems to be running scripts that happen to be living inside a module's directory, which I've always seen as an antipattern. To make me change my mind you'd have to convince me that it isn't.
我对此以及任何其他提议的
__main__机器摆弄都是-1 。唯一的用例似乎是运行恰好位于模块目录中的脚本,我一直将其视为反模式。为了让我改变主意,你必须让我相信事实并非如此。
Whether running scripts inside a package is an antipattern or not is subjective, but personally I find it really useful in a package I have which contains some custom wxPython widgets, so I can run the script for any of the source files to display a wx.Framecontaining only that widget for testing purposes.
在包内运行脚本是否是反模式是主观的,但我个人发现它在包含一些自定义 wxPython 小部件的包中非常有用,因此我可以为任何源文件运行脚本以显示wx.Frame仅包含用于测试目的的小部件。
回答by goffer
I ran into this issue. A hack workaround is importing via an if/else block like follows:
我遇到了这个问题。hack 解决方法是通过 if/else 块导入,如下所示:
#!/usr/bin/env python3
#myothermodule
if __name__ == '__main__':
from mymodule import as_int
else:
from .mymodule import as_int
# Exported function
def add(a, b):
return as_int(a) + as_int(b)
# Test function for module
def _test():
assert add('1', '1') == 2
if __name__ == '__main__':
_test()
回答by vaultah
Explanation
解释
From PEP 328
来自PEP 328
Relative imports use a module's __name__ attribute to determine that module's position in the package hierarchy. If the module's name does not contain any package information (e.g. it is set to '__main__') then relative imports are resolved as if the module were a top level module, regardless of where the module is actually located on the file system.
相对导入使用模块的 __name__ 属性来确定该模块在包层次结构中的位置。如果模块的名称不包含任何包信息(例如,它被设置为'__main__'), 那么相对导入将被解析为好像该模块是顶级模块,而不管该模块实际位于文件系统上的哪个位置。
At some point PEP 338conflicted with PEP 328:
... relative imports rely on __name__to determine the current module's position in the package hierarchy. In a main module, the value of __name__is always '__main__', so explicit relative imports will always fail (as they only work for a module inside a package)
...相对导入依赖于__name__来确定当前模块在包层次结构中的位置。在主模块中,__name__的值始终为'__main__',因此显式相对导入将始终失败(因为它们仅适用于包内的模块)
and to address the issue, PEP 366introduced the top level variable __package__:
为了解决这个问题,PEP 366引入了顶级变量__package__:
By adding a new module level attribute, this PEP allows relative imports to work automatically if the module is executed using the -mswitch. A small amount of boilerplate in the module itself will allow the relative imports to work when the file is executed by name. [...] When it [the attribute] is present, relative imports will be based on this attribute rather than the module __name__attribute. [...] When the main module is specified by its filename, then the __package__attribute will be set to None. [...] When the import system encounters an explicit relative import in a module without __package__ set (or with it set to None), it will calculate and store the correct value(__name__.rpartition('.')[0] for normal modulesand __name__for package initialisation modules)
通过添加新的模块级别属性,如果使用-m开关执行模块,则此 PEP 允许相对导入自动工作。当文件按名称执行时,模块本身中的少量样板将允许相关导入工作。[...] 当它 [属性] 存在时,相对导入将基于此属性而不是模块__name__属性。[...] 当主模块由其文件名指定时,__package__属性将设置为None。[...]当导入系统在没有 __package__ 设置(或设置为 None)的模块中遇到显式相对导入时,它将计算并存储正确的值(__name__.rpartition('.')[0] 用于普通模块和__name__用于包初始化模块)
(emphasis mine)
(强调我的)
If the __name__is '__main__', __name__.rpartition('.')[0]returns empty string. This is why there's empty string literal in the error description:
如果__name__是'__main__',则__name__.rpartition('.')[0]返回空字符串。这就是错误描述中有空字符串文字的原因:
SystemError: Parent module '' not loaded, cannot perform relative import
The relevant part of the CPython's PyImport_ImportModuleLevelObjectfunction:
CPythonPyImport_ImportModuleLevelObject函数的相关部分:
if (PyDict_GetItem(interp->modules, package) == NULL) {
PyErr_Format(PyExc_SystemError,
"Parent module %R not loaded, cannot perform relative "
"import", package);
goto error;
}
CPython raises this exception if it was unable to find package(the name of the package) in interp->modules(accessible as sys.modules). Since sys.modulesis "a dictionary that maps module names to modules which have already been loaded", it's now clear that the parent module must be explicitly absolute-imported before performing relative import.
如果 CPython 无法package在interp->modules(可访问为sys.modules)中找到(包的名称),则会引发此异常。由于sys.modules是“将模块名称映射到已经加载的模块的字典”,现在很清楚在执行相对导入之前必须显式绝对导入父模块。
Note:The patch from the issue 18018has added another ifblock, which will be executed beforethe code above:
注意:issue 18018的补丁增加了一个ifblock,会在上面的代码之前执行:
if (PyUnicode_CompareWithASCIIString(package, "") == 0) {
PyErr_SetString(PyExc_ImportError,
"attempted relative import with no known parent package");
goto error;
} /* else if (PyDict_GetItem(interp->modules, package) == NULL) {
...
*/
If package(same as above) is empty string, the error message will be
如果package(同上)为空字符串,则错误信息为
ImportError: attempted relative import with no known parent package
However, you will only see this in Python 3.6 or newer.
但是,您只会在 Python 3.6 或更高版本中看到这一点。
Solution #1: Run your script using -m
解决方案 #1:使用 -m 运行脚本
Consider a directory (which is a Python package):
考虑一个目录(这是一个 Python包):
.
├── package
│?? ├── __init__.py
│?? ├── module.py
│?? └── standalone.py
All of the files in packagebegin with the same 2 lines of code:
package 中的所有文件都以相同的 2 行代码开头:
from pathlib import Path
print('Running' if __name__ == '__main__' else 'Importing', Path(__file__).resolve())
I'm including these two lines onlyto make the order of operations obvious. We can ignore them completely, since they don't affect the execution.
我包括这两行只是为了使操作的顺序显而易见。我们可以完全忽略它们,因为它们不会影响执行。
__init__.pyand module.pycontain only those two lines (i.e., they are effectively empty).
__init__.py和module.py只包含这两行(即它们实际上是空的)。
standalone.pyadditionally attempts to import module.pyvia relative import:
standalone.py还尝试通过相对导入来导入module.py:
from . import module # explicit relative import
We're well aware that /path/to/python/interpreter package/standalone.pywill fail. However, we can run the module with the -mcommand line optionthat will "search sys.pathfor the named module and execute its contents as the __main__module":
我们很清楚这/path/to/python/interpreter package/standalone.py会失败。但是,我们可以使用-m命令行选项运行模块,该选项将“搜索sys.path命名模块并将其内容作为__main__模块执行”:
vaultah@base:~$ python3 -i -m package.standalone
Importing /home/vaultah/package/__init__.py
Running /home/vaultah/package/standalone.py
Importing /home/vaultah/package/module.py
>>> __file__
'/home/vaultah/package/standalone.py'
>>> __package__
'package'
>>> # The __package__ has been correctly set and module.py has been imported.
... # What's inside sys.modules?
... import sys
>>> sys.modules['__main__']
<module 'package.standalone' from '/home/vaultah/package/standalone.py'>
>>> sys.modules['package.module']
<module 'package.module' from '/home/vaultah/package/module.py'>
>>> sys.modules['package']
<module 'package' from '/home/vaultah/package/__init__.py'>
-mdoes all the importing stuff for you and automatically sets __package__, but you can do that yourself in the
-m为您完成所有导入工作并自动设置__package__,但您可以在
Solution #2: Set __package__ manually
解决方案#2:手动设置 __package__
Please treat it as a proof of concept rather than an actual solution. It isn't well-suited for use in real-world code.
请将其视为概念证明而不是实际解决方案。它不太适合在实际代码中使用。
PEP 366has a workaround to this problem, however, it's incomplete, because setting __package__alone is not enough. You're going to need to import at least Npreceding packages in the module hierarchy, where Nis the number of parent directories (relative to the directory of the script) that will be searched for the module being imported.
PEP 366有一个解决这个问题的方法,但是,它是不完整的,因为__package__单独设置是不够的。您将需要在模块层次结构中至少导入N 个前面的包,其中N是将搜索要导入的模块的父目录的数量(相对于脚本的目录)。
Thus,
因此,
Add the parent directory of the Nthpredecessor of the current module to
sys.pathRemove the current file's directory from
sys.pathImport the parent module of the current module using its fully-qualified name
Set
__package__to the fully-qualified name from 2Perform the relative import
将当前模块的第 N 个前驱的父目录添加到
sys.path从当前文件的目录中删除
sys.path使用其完全限定名称导入当前模块的父模块
设置
__package__为完全合格的名字从2执行相对导入
I'll borrow files from the Solution #1and add some more subpackages:
我将从解决方案 #1 中借用文件并添加更多子包:
package
├── __init__.py
├── module.py
└── subpackage
├── __init__.py
└── subsubpackage
├── __init__.py
└── standalone.py
This time standalone.pywill import module.pyfrom the packagepackage using the following relative import
这次standalone.py会使用下面的相对导入从包中导入module.py
from ... import module # N = 3
We'll need to precede that line with the boilerplate code, to make it work.
我们需要在该行之前添加样板代码,以使其工作。
import sys
from pathlib import Path
if __name__ == '__main__' and __package__ is None:
file = Path(__file__).resolve()
parent, top = file.parent, file.parents[3]
sys.path.append(str(top))
try:
sys.path.remove(str(parent))
except ValueError: # Already removed
pass
import package.subpackage.subsubpackage
__package__ = 'package.subpackage.subsubpackage'
from ... import module # N = 3
It allows us to execute standalone.pyby filename:
它允许我们按文件名执行standalone.py:
vaultah@base:~$ python3 package/subpackage/subsubpackage/standalone.py
Running /home/vaultah/package/subpackage/subsubpackage/standalone.py
Importing /home/vaultah/package/__init__.py
Importing /home/vaultah/package/subpackage/__init__.py
Importing /home/vaultah/package/subpackage/subsubpackage/__init__.py
Importing /home/vaultah/package/module.py
A more general solution wrapped in a function can be found here. Example usage:
可以在此处找到包含在函数中的更通用的解决方案。用法示例:
if __name__ == '__main__' and __package__ is None:
import_parents(level=3) # N = 3
from ... import module
from ...module.submodule import thing
Solution #3: Use absolute imports and setuptools
解决方案#3:使用绝对导入和设置工具
The steps are -
步骤是——
Replace explicit relative imports with equivalent absolute imports
Install
packageto make it importable
用等效的绝对导入替换显式相对导入
安装
package以使其可导入
For instance, the directory structure may be as follows
例如,目录结构可能如下
.
├── project
│?? ├── package
│?? │?? ├── __init__.py
│?? │?? ├── module.py
│?? │?? └── standalone.py
│?? └── setup.py
where setup.pyis
其中setup.py是
from setuptools import setup, find_packages
setup(
name = 'your_package_name',
packages = find_packages(),
)
The rest of the files were borrowed from the Solution #1.
其余的文件是从解决方案#1中借来的。
Installation will allow you to import the package regardless of your working directory (assuming there'll be no naming issues).
安装将允许您导入包,而不管您的工作目录如何(假设没有命名问题)。
We can modify standalone.pyto use this advantage (step 1):
我们可以修改standalone.py来利用这个优势(步骤 1):
from package import module # absolute import
Change your working directory to projectand run /path/to/python/interpreter setup.py install --user(--userinstalls the package in your site-packages directory) (step 2):
将您的工作目录更改为project并运行/path/to/python/interpreter setup.py install --user(--user在您的站点包目录中安装包)(步骤 2):
vaultah@base:~$ cd project
vaultah@base:~/project$ python3 setup.py install --user
Let's verify that it's now possible to run standalone.pyas a script:
让我们验证现在是否可以将standalone.py作为脚本运行:
vaultah@base:~/project$ python3 -i package/standalone.py
Running /home/vaultah/project/package/standalone.py
Importing /home/vaultah/.local/lib/python3.6/site-packages/your_package_name-0.0.0-py3.6.egg/package/__init__.py
Importing /home/vaultah/.local/lib/python3.6/site-packages/your_package_name-0.0.0-py3.6.egg/package/module.py
>>> module
<module 'package.module' from '/home/vaultah/.local/lib/python3.6/site-packages/your_package_name-0.0.0-py3.6.egg/package/module.py'>
>>> import sys
>>> sys.modules['package']
<module 'package' from '/home/vaultah/.local/lib/python3.6/site-packages/your_package_name-0.0.0-py3.6.egg/package/__init__.py'>
>>> sys.modules['package.module']
<module 'package.module' from '/home/vaultah/.local/lib/python3.6/site-packages/your_package_name-0.0.0-py3.6.egg/package/module.py'>
Note: If you decide to go down this route, you'd be better off using virtual environmentsto install packages in isolation.
注意:如果您决定走这条路,最好使用虚拟环境来隔离安装软件包。
Solution #4: Use absolute imports and some boilerplate code
解决方案#4:使用绝对导入和一些样板代码
Frankly, the installation is not necessary - you could add some boilerplate code to your script to make absolute imports work.
坦率地说,安装不是必需的 - 您可以在脚本中添加一些样板代码以使绝对导入工作。
I'm going to borrow files from Solution #1and change standalone.py:
我将从解决方案#1 中借用文件并更改standalone.py:
Add the parent directory of packageto
sys.pathbeforeattempting to import anything from packageusing absolute imports:import sys from pathlib import Path # if you haven't already done so file = Path(__file__).resolve() parent, root = file.parent, file.parents[1] sys.path.append(str(root)) # Additionally remove the current file's directory from sys.path try: sys.path.remove(str(parent)) except ValueError: # Already removed passReplace the relative import by the absolute import:
from package import module # absolute import
在尝试使用绝对导入从包中导入任何内容之前,将包的父目录添加到:
sys.pathimport sys from pathlib import Path # if you haven't already done so file = Path(__file__).resolve() parent, root = file.parent, file.parents[1] sys.path.append(str(root)) # Additionally remove the current file's directory from sys.path try: sys.path.remove(str(parent)) except ValueError: # Already removed pass用绝对导入替换相对导入:
from package import module # absolute import
standalone.pyruns without problems:
standalone.py运行没有问题:
vaultah@base:~$ python3 -i package/standalone.py
Running /home/vaultah/package/standalone.py
Importing /home/vaultah/package/__init__.py
Importing /home/vaultah/package/module.py
>>> module
<module 'package.module' from '/home/vaultah/package/module.py'>
>>> import sys
>>> sys.modules['package']
<module 'package' from '/home/vaultah/package/__init__.py'>
>>> sys.modules['package.module']
<module 'package.module' from '/home/vaultah/package/module.py'>
I feel that I should warn you: try not to do this, especiallyif your project has a complex structure.
我觉得我应该警告你:尽量不要这样做,特别是如果你的项目结构复杂。
As a side note, PEP 8recommends the use of absolute imports, but states that in some scenarios explicit relative imports are acceptable:
作为旁注,PEP 8建议使用绝对导入,但指出在某些情况下显式相对导入是可以接受的:
Absolute imports are recommended, as they are usually more readable and tend to be better behaved (or at least give better error messages). [...] However, explicit relative imports are an acceptable alternative to absolute imports, especially when dealing with complex package layouts where using absolute imports would be unnecessarily verbose.
推荐使用绝对导入,因为它们通常更具可读性并且往往表现更好(或至少给出更好的错误消息)。[...] 然而,显式相对导入是绝对导入的可接受替代方案,尤其是在处理复杂的包布局时,使用绝对导入会不必要地冗长。
回答by Salt999
if both packages are in your import path (sys.path), and the module/class you want is in example/example.py, then to access the class without relative import try:
如果两个包都在您的导入路径 (sys.path) 中,并且您想要的模块/类在 example/example.py 中,那么要访问没有相对导入的类,请尝试:
from example.example import fkt
回答by fralau
To obviate this problem, I devised a solution with the repackagepackage, which has worked for me for some time. It adds the upper directory to the lib path:
为了避免这个问题,我设计了一个带有repackage包的解决方案,它对我有用了一段时间。它将上层目录添加到 lib 路径中:
import repackage
repackage.up()
from mypackage.mymodule import myfunction
Repackage can make relative imports that work in a wide range of cases, using an intelligent strategy (inspecting the call stack).
使用智能策略(检查调用堆栈),重新打包可以使相对导入适用于各种情况。
回答by am5
Put this inside your package's __init__.py file:
把它放在你包的 __init__.py 文件中:
# For relative imports to work in Python 3.6
import os, sys; sys.path.append(os.path.dirname(os.path.realpath(__file__)))
Assuming your package is like this:
假设你的包是这样的:
├── project
│ ├── package
│ │ ├── __init__.py
│ │ ├── module1.py
│ │ └── module2.py
│ └── setup.py
Now use regular imports in you package, like:
现在在您的包中使用常规导入,例如:
# in module2.py
from module1 import class1
This works in both python 2 and 3.
这适用于 python 2 和 3。
回答by LaCroixed
Hopefully, this will be of value to someone out there - I went through half a dozen stackoverflow posts trying to figure out relative imports similar to whats posted above here. I set up everything as suggested but I was still hitting ModuleNotFoundError: No module named 'my_module_name'
希望这对那里的人有价值 - 我浏览了六篇stackoverflow帖子,试图找出与上面发布的内容类似的相对导入。我按照建议设置了所有内容,但我仍然在打ModuleNotFoundError: No module named 'my_module_name'
Since I was just developing locally and playing around, I hadn't created/run a setup.pyfile. I also hadn't apparently set my PYTHONPATH.
由于我只是在本地开发和玩耍,我还没有创建/运行setup.py文件。我也显然没有设置我的PYTHONPATH.
I realized that when I ran my code as I had been when the tests were in the same directory as the module, I couldn't find my module:
我意识到,当我运行我的代码时,当测试与模块位于同一目录中时,我找不到我的模块:
$ python3 test/my_module/module_test.py 2.4.0
Traceback (most recent call last):
File "test/my_module/module_test.py", line 6, in <module>
from my_module.module import *
ModuleNotFoundError: No module named 'my_module'
However, when I explicitly specified the path things started to work:
但是,当我明确指定路径时,事情开始起作用了:
$ PYTHONPATH=. python3 test/my_module/module_test.py 2.4.0
...........
----------------------------------------------------------------------
Ran 11 tests in 0.001s
OK
So, in the event that anyone has tried a few suggestions, believes their code is structured correctly and still finds themselves in a similar situation as myself try either of the following if you don't export the current directory to your PYTHONPATH:
因此,如果有人尝试了一些建议,相信他们的代码结构正确,并且仍然发现自己处于与我类似的情况,如果您不将当前目录导出到 PYTHONPATH,请尝试以下任一方法:
- Run your code and explicitly include the path like so:
$ PYTHONPATH=. python3 test/my_module/module_test.py - To avoid calling
PYTHONPATH=., create asetup.pyfile with contents like the following and runpython setup.py developmentto add packages to the path:
- 运行您的代码并显式包含路径,如下所示:
$ PYTHONPATH=. python3 test/my_module/module_test.py - 为避免调用
PYTHONPATH=.,请创建一个setup.py包含如下内容的文件并运行python setup.py development以将包添加到路径:
# setup.py from setuptools import setup, find_packages setup( name='sample', packages=find_packages() )
# setup.py from setuptools import setup, find_packages setup( name='sample', packages=find_packages() )
回答by árthur
I needed to run python3 from the main project directory to make it work.
我需要从主项目目录运行 python3 才能使其工作。
For example, if the project has the following structure:
例如,如果项目具有以下结构:
project_demo/
├── main.py
├── some_package/
│ ├── __init__.py
│ └── project_configs.py
└── test/
└── test_project_configs.py
Solution
解决方案
I would run python3 inside folder project_demo/and then perform a
我会在文件夹project_demo/ 中运行 python3 ,然后执行
from some_package import project_configs
回答by Taras Kucherenko
回答by Thomas Heckmann
I had a similar problem: I needed a Linux service and cgi plugin which use common constants to cooperate. The 'natural' way to do this is to place them in the init.py of the package, but I cannot start the cgi plugin with the -m parameter.
我有一个类似的问题:我需要一个使用通用常量来协作的 Linux 服务和 cgi 插件。执行此操作的“自然”方法是将它们放在包的init.py 中,但我无法使用 -m 参数启动 cgi 插件。
My final solution was similar to Solution #2 above:
我的最终解决方案类似于上面的解决方案#2:
import sys
import pathlib as p
import importlib
pp = p.Path(sys.argv[0])
pack = pp.resolve().parent
pkg = importlib.import_module('__init__', package=str(pack))
The disadvantage is that you must prefix the constants (or common functions) with pkg:
缺点是必须在常量(或常用函数)前加上 pkg:
print(pkg.Glob)

