Python模块中的全局状态

Python模块中的全局状态,python,module,coding-style,global-variables,Python,Module,Coding Style,Global Variables,我正在使用cffi为C库编写Python包装器 必须初始化并关闭C库。另外,cffi需要一些地方来保存从ffi.dlopen()返回的状态 我可以在这里看到两条路径: 要么我把这整个有状态的事情都放在这样一个类中 class wrapper(object): def __init__(self): self.c = ffi.dlopen("mylibrary") self.c.initialize() def __del__(self):

我正在使用
cffi
为C库编写Python包装器

必须初始化并关闭C库。另外,
cffi
需要一些地方来保存从
ffi.dlopen()
返回的状态

我可以在这里看到两条路径:

要么我把这整个有状态的事情都放在这样一个类中

class wrapper(object):
    def __init__(self):
        self.c = ffi.dlopen("mylibrary")
        self.c.initialize()
    def __del__(self):
        self.c.terminate()
或者我提供了两个全局函数,它们将状态隐藏在全局变量中

def initialize():
    global __library 
    __library = ffi.dlopen("mylibrary")
    __library.initialize()
def terminate():
    __library.terminate()
    del __library
第一条路径有点麻烦,因为它要求用户始终创建一个对象,该对象除了管理库状态之外没有其他用途。另一方面,它确保每次实际调用
terminate()

第二条路径似乎产生了一个更简单的API。然而,它暴露了一些隐藏的全局状态,这可能是一件坏事。此外,如果用户忘记调用
terminate()
,则C库没有正确卸载(这在C端不是一个大问题)


这些路径中哪一条更符合python?

只有在python中,如果库实际上支持一个应用程序中的多个实例,那么公开包装器对象才有意义。如果它不支持这一点,或者它与kindall的建议不太相关,只需在导入时初始化库,并添加atexit处理程序进行清理

在无状态api或甚至不支持保持不同状态集的api周围添加包装器并不是真正的pythonic,并且会增加不同实例具有某种隔离的期望

示例代码:

import atexit

# Normal library initialization
__library = ffi.dlopen("mylibrary")
__library.initialize()

# Private library cleanup function
def __terminate():
    __library.terminate()
# register function to be called on clean interpreter termination
atexit.register(__terminate)

有关atexit的更多详细信息,当然也有一些详细信息。

有什么理由不在导入模块时初始化库(并将必要的引用存储在模块全局中)?@kindall我该如何调用
terminate()
呢?你说如果不调用,那没什么大不了的。但是如果它需要调用,那么唯一可靠的方法就是让库的用户调用它。无论如何,你不能指望
\uu del\uu
。不过,上下文管理器可能有意义。。。