简体   繁体   English

子包和__init__.py

[英]Sub packages and __init__.py

So, this is a set of questions about how to use __init__.py in packages/sub-packages. 因此,这是有关如何在包/子包中使用__init__.py的一系列问题。 I have searched, and surprisingly not found a decent answer to this. 我进行了搜索,但出乎意料的是,找不到合适的答案。

If I have the following structure (which is just a simplified example obviously): 如果我具有以下结构(显然只是一个简化的示例):

my_package/
  __init__.py
  module1.py
  my_sub_package/
    __init__.py
    module2.py

the contents of module1.py is module1.py的内容是

my_string = 'Hello'

the contents of module2.py is module2.py的内容是

my_int = 42

First question: importing multiple modules from a package by default 第一个问题:默认情况下从一个包中导入多个模块

What should be in the __init__.py files? __init__.py文件中应该包含什么?

I can leave them empty, in which case, import my_package does nothing really (obviously it imports the package, but the package effectively contains nothing). 我可以将它们留空,在这种情况下, import my_package确实不执行任何操作(显然,它导入了程序包,但该程序包实际上不包含任何内容)。 This is fine obviously, and what should happen in most cases. 显然,这很好,并且在大多数情况下会发生什么。

What I'd like in this case though is for import my_package to allow me to use my_package.module1.my_string and my_package.my_sub_package.module2.my_int . 在这种情况下,我想要的是import my_package以允许我使用my_package.module1.my_stringmy_package.my_sub_package.module2.my_int

I can add __all__ = [ 'module1' ] to my_package/__init__.py and __all__ = [ 'module2' ] to my_package/my_sub_package/__init__.py, but this only affects imports using a wildcard as I understand it (so only from my_package import * and from my_package.my_sub_package import * ). 我可以在my_package / __ init__.py中添加__all__ = [ 'module1' ] module1 __all__ = [ 'module1' ]在my_package / my_sub_package / __ init__.py中添加__all__ = [ 'module2' ] ,但这只会影响使用通配符的导入(据我所知(仅从from my_package import *from my_package.my_sub_package import * )。

I can achieve this by putting 我可以通过把

import my_package.module1
import my_package.my_sub_package

in my_package/__init__.py and 在my_package / __ init__.py和

import my_package.my_sub_package.module2

in my_package/my_sub_package/__init__.py, but is this a bad idea? 在my_package / my_sub_package / __ init__.py中,但这是一个坏主意吗? It creates a (seemingly) infinite series of my_package.my_package.my_package.... when I do this in the Python interpreter (3.5.5). 当我在Python解释器(3.5.5)中执行此操作时,它将创建(看似)无限个my_package.my_package.my_package ....系列。

Separate, but highly related, question: using modules to keep files reasonably sized 单独但高度相关的问题:使用模块来保持文件的合理大小

If I wanted instead to be able to do the following 如果我希望能够执行以下操作

import my_package
print(my_package.my_string)
print(str(my_package.my_sub_package.my_int))

ie I wanted to use module1 and module2 purely for separating code into smaller more readable files if I actually had lots of modules in each package (which obviously doesn't apply in this trivial example, but can easily) 也就是说,如果我实际上在每个包中都有很多模块,我想纯粹使用module1和module2将代码分离为更小可读的文件(显然,这在这个琐碎的示例中并不适用,但可以轻松实现)

is doing from my_package.module1 import * in my_package/__init__.py and from my_package.my_sub_package.module2 import * in my_package/my_sub_package/__init__.py a reasonable way to do that? from my_package.module1 import * / __ init__.py中的from my_package.my_sub_package.module2 import *和my_package / my_sub_package / __ init__.py中的from my_package.my_sub_package.module2 import *做的合理方法吗? I don't like the use of the wildcard import, but it seems like it would be impractically verbose to import everything defined in a (real) module, listing them all. 我不喜欢使用通配符导入,但是导入(实际)模块中定义的所有内容并列出所有内容似乎不切实际。

Third (also highly related) question: avoiding writing the package names in multiple places 第三个(也是高度相关的)问题:避免在多个位置写软件包名称

Is there a way I can achieve the above without having to put the names of the packages into the source code in them? 有没有一种方法可以实现上述目的而不必将包的名称放入其中的源代码中? I ask because I'd like to avoid having to change it in multiple places if I renamed the package (again, simple in this trivial example, can be done by an IDE or script in reality, but would be nice to know how to avoid). 我问是因为如果我重命名了软件包,我想避免不得不在多个地方进行更改(同样,在这个简单的示例中,很简单,可以在现实中由IDE或脚本来完成,但是很高兴知道如何避免)。

In my_package/__init__.py , use my_package/__init__.py ,使用

from . import my_sub_package

etc. 等等
See for example NumPy's __init__.py , which has from . import random 例如,参见NumPy的__init__.py ,该文件from . import random from . import random , and allows from . import random ,并允许

import numpy as np
np.random.random

Wildcard imports inside a single package tend to be common, provided you have __all__ defined in the modules and subpackages you import from. 如果在导入的模块和子包中定义了__all__ ,则单个包中的通配符导入很常见。 Again an example from NumPy's __init__.py , which has several wildcard imports. 还是NumPy的__init__.py的示例,该示例具有多个通配符导入。

Here's part of that __init__.py : 这是__init__.py的一部分:

from . import core
from .core import *
from . import compat
from . import lib
from .lib import *
from . import linalg
from . import fft
from . import polynomial
from . import random
from . import ctypeslib
from . import ma
from . import matrixlib as _mat
from .matrixlib import *
from .compat import long

Notice also the two core import lines. 还要注意两条core导入线。 Both numpy.core and the core definitions (functions, classes etc) are then available. numpy.core和核心定义(函数,类等)都可用。

When in doubt how to do something, or whether something is good practice, have a look at a few well-known libraries or packages. 如果不确定如何做某事,或者某事是否是一种好的做法,请查看一些知名的库或程序包。 That can help gaining some valuable insights. 这可以帮助您获得一些有价值的见解。

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

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