简体   繁体   English

如何在同一 python package 中的模块之间设置导入和依赖关系

[英]How to setup imports and dependencies between modules in the same python package

I am writing a library in python.我正在 python 中编写一个库。 It has one package and 3 modules, such as它有一个 package 和 3 个模块,如

mypackage
    __init__.py
    utils.py
    fileio.py
    math.py

If I just leave the __init__.py empty, my users must figure out which functions are in which modules, which is annoying.如果我只是将__init__.py留空,我的用户必须弄清楚哪些函数在哪些模块中,这很烦人。 The fact that I have three modules is an implementation detail that is not important.我拥有三个模块这一事实是一个不重要的实现细节。

Maybe I should import the main functions into the __init__.py , like this也许我应该将主要功能导入__init__.py ,就像这样

from .utils import create_table
from .fileio import save_rows, load_rows
from .math import matrix_inverse

so that my users can just do这样我的用户就可以做到

import mypackage as myp

rows = myp.load_rows()

Is that best practice?这是最佳做法吗?

What about the alternative to put ALL symbols into the __init__.py , such as将所有符号放入__init__.py的替代方案怎么样,例如

from .utils import *
from .fileio import *
from .math import *

And if there are any functions that I don't want to expose, I will prefix them with underscore.如果有任何我不想公开的功能,我会在它们前面加上下划线。 Is that better?那个更好吗? It certainly is easier for me.这对我来说当然更容易。

What if the fileio.py needs to call some functions in the utils.py ?如果fileio.py需要调用utils.py中的一些函数怎么办? I could put我可以把

from .utils import *

into the fileio.py , but won't that create a circular or redundant reference?进入fileio.py ,但这不会创建循环或冗余引用吗? What's the best way to handle this?处理这个问题的最佳方法是什么?

Maybe I should import the main functions into the init .py, like this [...] Is that best practice?也许我应该将主要功能导入init .py,像这样 [...] 这是最佳实践吗?

I wouldn't say there is a "best practice", it depends on the specific case, but this is surely pretty common: you define a bunch of stuff in each module, and import the relevant ones in __init__ .我不会说有“最佳实践”,它取决于具体情况,但这肯定很常见:您在每个模块中定义一堆东西,并在__init__中导入相关的东西。 This is an easy way to not bother the users with remembering which submodule has the needed function, however it can get pretty annoying if you have a lot of functions to import from each module.这是一种不用担心用户记住哪个子模块具有所需的 function 的简单方法,但是如果您要从每个模块导入很多函数,它会变得非常烦人。

What about the alternative to put ALL symbols into the init .py, such as将所有符号放入init .py 的替代方案怎么样,例如

from.utils import * from.fileio import * from.math import *

You most likely don't want to do this.你很可能不想这样做。 This import everything in the user module, including other imported modules and internal functions.这会导入用户模块中的所有内容,包括其他导入的模块和内部函数。 You should avoid it.你应该避免它。

What if the fileio.py needs to call some functions in the utils.py?如果fileio.py需要调用utils.py中的一些函数怎么办? [...] won't that create a circular or redundant reference? [...] 这不会创建循环或冗余引用吗?

Yeah, that is something that can happen and you usually want to avoid it at all costs.是的,这是可能发生的事情,你通常想不惜一切代价避免它。 If you need some functions from utils.py in fileio.py , you should import them explicitly as from.utils import x, y, z .如果您需要utils.py中的fileio.py中的某些功能,则应将它们显式导入为from.utils import x, y, z Remember to also always use relative imports when importing things between modules of the same package (ie use from.utils import x , not from package.utils import x ).请记住,在相同 package 的模块之间导入内容时也始终使用相对导入(即使用from.utils import x ,而不是from package.utils import x )。


A good compromise between these two options you mention which solves most of the above problems (although not circular imports, you would have to avoid those yourself) would be to define an __all__ list inside each one of your modules to specify which functions should be exported when using from x import * , like this:您提到的这两个选项之间的一个很好的折衷方案可以解决上述大多数问题(尽管不是循环导入,但您必须自己避免这些问题)是在每个模块中定义一个__all__列表以指定应该导出哪些函数使用from x import *时,如下所示:

# utils.py

import sys

__all__ = ['user_api_one', 'user_api_two']

def user_api_one():
    ...

def user_api_two():
    ...

def internal_function():
    ...

If you properly define an __all__ list in all your modules, then in your __init__.py you will be able to safely do:如果您在所有模块中正确定义了一个__all__列表,那么在您的__init__.py中,您将能够安全地执行以下操作:

from .utils import *
from .fileio import *
from .math import *

This will only import relevant functions (for example user_api_one and user_api_two for utils , and not internal_function nor sys ).只会导入相关函数(例如user_api_oneuser_api_two用于utils ,而不是internal_functionsys )。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM