简体   繁体   English

如何在模块中定义一个 `from ... import *' api 与 __all__ 分开?

[英]How to define a `from … import *' api seperate from __all__ in a module?

I have a module which is split roughly in half between utility type functions and core api functions.我有一个模块,它在实用程序类型函数和核心 api 函数之间大致分成两半。 I need to have all of them in __all__ in order to have help() be useful, and also to specify which of the many functions/classes/etc in the module are for external use, but I also want to support from mymodule import * as a way to get just the core functionality into other modules.我需要将它们全部放在__all__中才能使help()有用,并且还要指定模块中的许多函数/类/等中的哪些是供外部使用的,但我也想支持from mymodule import *作为将核心功能引入其他模块的一种方式。 Is there a way to do that?有没有办法做到这一点?

Almost.几乎。 While you can't have __all__ do double duty in this way, you can add your own virtual api module which can then be imported...虽然您不能以这种方式让__all__执行双重任务,但您可以添加自己的虚拟 api 模块,然后可以将其导入...

class fake_module(object):
    def __init__(self, name, *args):
        self.name = name
        self.__all__ = []
        all_objects = globals()
        for name in args:
            self.__dict__[name] = all_objects[name]
            self.__all__.append(name)
    def register(self):
        sys.modules["%s.%s" % (__name__, self.name)] = self

    fake_module('api', 'class1', 'class2', 'func3', 'exception4').register()

Then in the other modules instead of from mymodule import * you can do from mymodule.api import * to get just the desired subset while still keeping everything in a single module.然后在其他模块中,而不是from mymodule import *您可以from mymodule.api import *获得所需的子集,同时仍将所有内容保存在单个模块中。

Note : from... import * is not usually good practice, and should be used with great care and only with modules/packages that explicity state that they have been designed with such usage in mind.注意from... import *通常不是好的做法,应该非常小心地使用,并且只能与明确指出 state 的模块/包一起使用,它们的设计考虑了这种用法。

Ethan, your fake_module is likely better accomplished with plain old python. Ethan,你的fake_module可能用普通的旧 python 更好地完成。 Just move your code into a directory setup:只需将您的代码移动到目录设置中:

mymodule
    __init__.py
    api.py
    util.py
    _mymodule.py

Where _mymodule.py contains your current code.其中_mymodule.py包含您当前的代码。

In your __init__.py :在您的__init__.py中:

from _mymodule import * 

In you're api.py你是api.py

# explicity import only those api classes you want to expose
# this will allow you to call `from mymodule.api import *`
import from _mymodule ApiClass1
import from _mymodule ApiClass2
# etc  

Do the same for your util.py对你的util.py做同样的事情

# explicity import only those util classes you want to expose
# this will allow you to call `from mymodule.util import *`
import from _mymodule UtilClass1
import from _mymodule UtilClass2
# etc

So now you can:所以现在你可以:

# import everything willy nilly for your help()
from mymodule import *

# or import only the "public" values from api and util
from mymodule.api import *
from mymodule.util import *

Breaking up your code like this can be useful for organizing a largish module that you still want to be able to access from a top level namespace.像这样分解你的代码对于组织一个你仍然希望能够从顶级命名空间访问的大型模块很有用。 But I would have to agree with brandizzi that using from mymodule import * in code that is using this module is generally a bad idea.但我不得不同意brandizzi的观点,即在使用该模块的代码中使用from mymodule import *通常是个坏主意。 What you gain in ease of importing you lose in transparency of the code that is using those imports.您在易于导入中获得的东西会在使用这些导入的代码的透明度上丢失。

I do not think there is a way to do it - at least not a clean way.我不认为有办法做到这一点 - 至少不是一种干净的方式。 Even the Python official modules have a lot of util functions appearing in its documentation.甚至 Python 官方模块在其文档中也有很多实用功能。 What I would do, if the separation is important, is to create two different modules.如果分离很重要,我会做的是创建两个不同的模块。 Anyway, to use from module import * is not a good practice and I would not recommend you to do it, much less to design your modules for fitting such practice:)无论如何,使用from module import *不是一个好习惯,我不建议你这样做,更不用说设计你的模块来适应这种做法了:)

You can't have what you want: import * behavior is defined by __all__ .你不能拥有你想要的: import *行为由__all__定义。

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

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