我应该从 __dir__ 方法隐藏 python 模块中依赖项的导入吗?

hau*_*tve 3 python python-module python-import python-3.x

我正在使用单个导入包制作一个 Python 分发包,该导入包具有多个模块(一个文件夹,多个文件)。该包具有在模块中导入的依赖项。当用户从导入包导入模块时,他们还可以访问在函数外部导入的依赖项。我已经找到了解决方法,但我不确定这是否是一个好主意。

模块joke.py的选项A

from markdown import markdown

def joke():
    return markdown("The Funniest Joke in the World")

Run Code Online (Sandbox Code Playgroud)

joke.py 模块的选项 B

def joke():
    from markdown import markdown
    return markdown("The Funniest Joke in the World")

Run Code Online (Sandbox Code Playgroud)

A在交互模式下的使用

>>> import joke
>>> joke.joke()
'The Funniest Joke in the World'
>>> dir(joke)
['__builtins__', '__cached__', '__doc__', '__file__', '__loader__', '__name__', '__package__', '__spec__', 'joke', 'markdown']
>>> joke.markdown("Not funny")
'<p>Not funny</p>'
Run Code Online (Sandbox Code Playgroud)

B在交互模式下的使用

>>> import joke
>>> dir(joke)
['__name__', '__doc__', '__package__', '__loader__', '__spec__', '__file__', '__cached__', '__builtins__', 'joke', 'markdown']
>>> joke.markdown("Not funny")
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
AttributeError: module 'joke' has no attribute 'markdown' 
Run Code Online (Sandbox Code Playgroud)

问题

我不想向用户公开依赖项,这意味着选项 B 更好。但是,如果所有导入都需要在类或函数内部,则代码会变得混乱。是否有更好的选择来实现 B 中的功能而不会使导入变得混乱?

我查看了一些包,看看是否可以使用 dir() 找到它们的任何依赖项,但感觉有点不知所措,因为我不知道它们有哪些依赖项或如何找到它们的依赖项。

a_g*_*est 5

从 Python 3.7 开始,您可以定义一个模块级__dir__函数,用于生成以下结果dir(module)

def __dir__():
    return ['joke']
Run Code Online (Sandbox Code Playgroud)

__all__这可以与处理导入相结合from module import *

__all__ = ['joke']

def __dir__():
    return __all__
Run Code Online (Sandbox Code Playgroud)

请注意,用户仍然可以访问这些依赖包,即joke.markdown仍然有效。如果你确实想限制这一点,你还可以定义一个模块级别__getattr__

def __getattr__(name):
    if name not in __all__:
        raise AttributeError(name)
    return globals()[name]
Run Code Online (Sandbox Code Playgroud)