我有一个包含与操作系统相关的模块的软件包。这些模块各自具有相同的API。
在客户端代码中,我可以执行以下操作:
import platform
if platform.system() == "Windows":
from my_package import os_win32 as my_package_platform
elif platform.system() == "Linux":
from my_package import os_linux as my_package_platform
# use my_package_platform in client code
但是我想做类似的事情
from my_package import my_package_platform
并自动导入正确的模块。
实际上有一个模块my_package_platform.py
:
import platform
import importlib as imp
import importlib.util as impu
import sys
exports = ["symbol1", "symbol2"]
def update_globals(mod, var_list):
for var in var_list:
globals()[var] = mod.__dict__.get(var)
if platform.system() == "Windows":
mod = imp.import_module(".os_win32", __package__)
elif platform.system() == "Linux":
mod = imp.import_module(".os_linux", __package__)
else:
raise NotImplementedError("not implemented for platform %s".format(platform.system()))
update_globals(mod, exports)
这似乎可行,但是似乎有些古怪。同样,必须保持exports
变量。
sys.meta_path
操作来创建“虚拟模块”在软件包的__init__.py
中添加以下内容:
import platform
import importlib.abc
import importlib.util as impu
import sys
class _VirtualModuleFinder(importlib.abc.MetaPathFinder):
def find_spec(self, fullname: str, path, target=None):
if fullname == __package__ + ".my_package_platform":
if platform.system() == "win32":
return impu.find_spec(__package__ + ".os_win32")
elif platform.system() == "Linux":
return impu.find_spec(__package__ + ".os_linux")
else:
return None
sys.meta_path.append(_VirtualModuleFinder())
这工作得非常优雅,但是似乎有点过大。另一方面,仅当通过其他方式找不到模块时才调用附加的Finder
。
一个警告是,模块规范将包含原始模块名称。 (这可能是错误或功能-我目前尚不完全了解其中的含义。)>
问题描述我有一个包含与操作系统相关的模块的软件包。这些模块各自具有相同的API。在客户端代码中,我可以执行以下操作:如果platform.system()==“ Windows”:...
[我认为我找到了一个被黑客入侵较少的解决方案,并且似乎在极端情况下更有效: