我在github上写了一个软件.它基本上是一个带有一些额外功能的托盘图标.我想提供一段工作代码而不必让用户安装本质上依赖于可选功能的东西,我实际上并不想导入我不会使用的东西所以我认为这样的代码将是"好的解决方案":
---- IN LOADING FUNCTION ---- features = [] for path in sys.path: if os.path.exists(os.path.join(path, 'pynotify')): features.append('pynotify') if os.path.exists(os.path.join(path, 'gnomekeyring.so')): features.append('gnome-keyring') #user dialog to ask for stuff #notifications available, do you want them enabled? dlg = ConfigDialog(features) if not dlg.get_notifications(): features.remove('pynotify') service_start(features ...) ---- SOMEWHERE ELSE ------ def service_start(features, other_config): if 'pynotify' in features: import pynotify #use pynotify...
但是有一些问题.如果用户格式化他的机器并安装最新版本的操作系统并重新部署此应用程序,则功能会在没有警告的情况下突然消失.解决方案是在配置窗口中显示:
if 'pynotify' in features: #gtk checkbox else: #gtk label reading "Get pynotify and enjoy notification pop ups!"
但是,如果这是一个mac,我怎么知道我不是在寻找一个他们永远无法填充的依赖关系的疯狂追逐用户?
第二个问题是:
if os.path.exists(os.path.join(path, 'gnomekeyring.so')):
问题.我可以确定该文件在所有Linux发行版中总是被称为gnomekeyring.so吗?
其他人如何测试这些功能?基本问题
try: import pynotify except: pynotify = disabled
是代码是全局的,这些可能会被乱七八糟,即使用户不想要pynotify ....它仍然是加载的.
那么人们认为什么是解决这个问题的最佳方法呢?
该try:
方法不需要是全局的 - 它可以在任何范围内使用,因此模块可以在运行时"延迟加载".例如:
def foo(): try: import external_module except ImportError: external_module = None if external_module: external_module.some_whizzy_feature() else: print("You could be using a whizzy feature right now, if you had external_module.")
运行脚本时,不会尝试加载external_module
.第一次foo()
调用,external_module
是(如果可用)加载并插入到函数的本地范围.后续调用foo()
重新external_module
插入其范围而无需重新加载模块.
一般来说,最好让Python处理导入逻辑 - 它已经做了一段时间了.:-)
你可能想看看imp模块,它基本上是你在上面手动完成的.因此,您可以首先查找模块,find_module()
然后通过load_module()
或通过简单地导入它(在检查配置后)加载它.
顺便说一句,如果使用除了:我总是会添加特定的异常(这里是ImportError),以免意外捕获无关的错误.