简体   繁体   English

Python模块使用从子模块导入到根命名空间的方法

[英]Python module with methods imported from a sub-module into root namespace

I want to create a Python module that works like NumPy. 我想创建一个像NumPy一样工作的Python模块。 The methods are not only sub-modules in the leaves of the tree from the module source. 这些方法不仅是模块源树中树叶的子模块。 There is a root module containing many methods that I can call directly, and there are also sub-modules. 有一个根模块包含我可以直接调用的许多方法,还有子模块。 The problem is the root methods must be defined somewhere. 问题是必须在某处定义根方法。 I was thinking to have a directory structure: 我想有一个目录结构:

module/
  __init__.py
  core.py
  stuff1.py
  submodule/
    __init__.py
    stuff2.py
    stuff3.py

Now that I want is for everything inside "core" to be imported into the "module" namespace, as if it were a module.py file, and the contents of core.py were inside this module.py. 现在我想要的是将“core”中的所有内容导入到“module”命名空间中,就好像它是一个module.py文件,而core.py的内容都在这个module.py中。 The problem is that module is a directory instead of a file, so how do I define these methods that should sit in the root of the module? 问题是模块是目录而不是文件,那么如何定义应该位于模块根目录中的这些方法呢?

I tried putting "from core import *" inside init .py, but that didn't work. 我尝试在init .py中添加“from core import *”,但这不起作用。 (EDIT: Actually it does.) (编辑:实际上确实如此。)

Should I have the core methods inside a "module.py" file, and also a module directory? 我应该在“module.py”文件中还有模块目录中的核心方法吗? I don't know if that works, but it looks pretty awkward. 我不知道这是否有效,但看起来很尴尬。

What I think you want is to be able to do this: 我认为你想要的是能够做到这一点:

# some_other_script.py

import module
# Do things using routines defined in module.core

What happens when you ask Python to import module is (in a very basic sense), module/__init__.py is run, and a module object is created and imported into your namespace. 当您要求Python import module时会发生什么(在非常基本的意义上),运行module/__init__.py ,并创建module对象并将其导入您的命名空间。 This object (again, very basically) encompasses the things that happened when __init__.py was run: name definitions and so on. 此对象(再次,非常基本)包含运行__init__.py时发生的事情:名称定义等。 These can be accessed through module.something . 这些可以通过module.something访问。

Now, if your setup looks like this: 现在,如果您的设置如下所示:

# module/__init__.py

from module.core import Clazz
c = Clazz()
print c # Note: demo only! Module-level side-effects are usually a bad idea!

When you import module , you'll see a print statement like this: 导入module ,您将看到如下的print语句:

<module.core.Clazz object at 0x00BBAA90>

Great. 大。 But if you then try to access c , you'll get a NameError : 但是如果你然后尝试访问c ,你会得到一个NameError

# some_other_script.py
import module # prints "<module.core.Clazz object at 0x00BBAA90>"
print c # NameError (c is not defined)

This is because you haven't imported c ; 这是因为你没有导入c ; you've imported module . 你已经导入了module If instead your entry-point script looks like this: 相反,您的入口点脚本如下所示:

# some_other_script.py
import module # prints "<module.core.Clazz object at 0x00BBAA90>"
print module.c  # Access c *within module*

Everything will run fine. 一切都会好起来的。 This will also work fine with from core import * and/or from module import * , but I (and PEP8) advise against that just because it's not very clear what's going on in the script when you start mucking around with wild imports. 可以from core import *和/或from module import * ,但我(和PEP8)建议不要这样做,因为当你开始使用野生导入时,脚本中发生了什么并不是很清楚。 For clarity: 为清楚起见:

# module/core.py

def core_func():
    return 1


# module/__init__.py

from core import *
def mod_func():
    return 2

The above is really pretty much fine, although you might as well make core "private" (rename to _core ) to indicate that there's no reason to touch it from outside the package anymore. 上面的确非常好,尽管您可能会将core “私有”(重命名为_core )表示没有理由再从包外接触它。

# some_other_script.py

from module import *

print core_func() # Prints 1
print mod_func() # Prints 2

Check out information about the __all__ list. 查看有关__all__列表的信息。 It allows you to define what names are exported. 它允许您定义导出的名称。

Tag it as such and you can setup a function to determine what to pull in from your submodules: 将其标记为此类,您可以设置一个函数来确定从子模块中提取的内容:

@property
all(self):
    #Whatever introspective code you may want for your modules
    __all__ += submodule.__all__

If you just want the whole damn shabang in module space, here's a way: 如果你只想在模块空间中使用该死的shabang,这里有一种方法:

$ ipython
In [1]: from foomod import *

In [2]: printbar()
Out[2]: 'Imported from a foreign land'

In [3]: ^D
Do you really want to exit ([y]/n)?
$ ls foomod/
__init__.py __init__.pyc    core.py         core.pyc        submodule
$ grep . foomod/*.py 
foomod/__init__.py:from foomod.core import *
foomod/core.py:def printbar():
foomod/core.py:     return "Imported from a foreign land"

... and if we make __init__.py empty: ...如果我们使__init__.py空:

$ echo > foomod/__init__.py
$ ipython

In [1]: from foomod import *

In [2]: printbar()
---------------------------------------------------------------------------
NameError                                 Traceback (most recent call last)
<ipython-input-2-ba5b6693441e> in <module>()
----> 1 printbar()

NameError: name 'printbar' is not defined

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

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