可选导入的pythonic方式
我有一个包,允许用户使用他们想要连接到数据库的4个包中的任何一个。它工作得很好,但我对我进口东西的方式不满意 我可以简单地导入所有软件包,但如果特定用户不需要使用可选导入的pythonic方式,python,import,Python,Import,我有一个包,允许用户使用他们想要连接到数据库的4个包中的任何一个。它工作得很好,但我对我进口东西的方式不满意 我可以简单地导入所有软件包,但如果特定用户不需要使用turbodbc,我不想这样做,例如: import pyodbc import pymssql import turbodbc from ibmdbpy.base import IdaDataBase 目前,我有以下情况。我尝试导入所有这些文件,但没有导入的文件,没有问题,我的程序只是假设不会调用它们,如果它们是错误的: # som
turbodbc
,我不想这样做,例如:
import pyodbc
import pymssql
import turbodbc
from ibmdbpy.base import IdaDataBase
目前,我有以下情况。我尝试导入所有这些文件,但没有导入的文件,没有问题,我的程序只是假设不会调用它们,如果它们是错误的:
# some envs may not have all these packages installed so we try each:
try:
import pyodbc
except:
pass
try:
import pymssql
except:
pass
try:
import turbodbc
except:
pass
try:
from ibmdbpy.base import IdaDataBase
except:
pass
这感觉不像是蟒蛇。所以我知道有些包,比如HoloView或tensorflow,允许您指定后端。它们当然比我的要复杂几个数量级,但它们必须处理相同的模式
我怎样才能使这个代码正确?这在技术上是错误的,因为如果他们打算使用pyodbc
,但没有安装它,我的程序不会警告他们,它会在运行时出错。所以这真的超越了美学或哲学;这是技术上容易出错的代码
你会如何处理这种情况
仅供参考,以下是如何调用代码的示例:
connect('Playground', package='pymssql')
可以将导入放置在文件开头以外的其他位置。“重新导入”某些东西实际上没有任何作用,因此频繁导入x在计算上并不昂贵:
def switch(x):
if x == 'a':
import json
json.load(file)
elif x == 'b':
import pandas as pd
pd.read_csv(file)
您还可以使用importlib
动态导入模块。如果要在同一API的多个实现之间进行选择,则这一点尤其有用
class Connection:
def __init__(self, driver_module, driver_name):
# or driver_module, driver_name = full_path.rsplit('.', 1)
self.driver = get_attr(importlib.load_module(driver_module), driver_name)()
def method(self):
return self.driver.do()
随后:
if pyodbc is None and user_wants_to_use_pyodbc:
print_warning()
raise SomeConfigurationErrorOrSuch()
这种方法适用于少量选项。如果您有足够的选项需要抽象出这种方法,那么您可以使用
importlib
模块在程序的控制下导入模块。我将使用importlib中的导入模块:
from importlib import import_module
modules_to_import = ['pyodbc', 'pymssql', 'turbodbc', 'ibmdbpy.base.IdaDataBase']
for m in modules_to_import:
try:
globals()[m.split('.')[-1]] = import_module(m)
except ModuleNotFoundError:
print('Module {} not found'.format(m))
我仍然不相信在所有答案中都提供了理想的解决方案,但谢谢sam,你的解决方案是我所采用的,它似乎最符合我的目的。后来在我的代码中,如您所建议的,我这样做了:
return locals()[f'use_{package}\u db2'](如果['pyodbc'、'IdaDataBase']中的包不是其他包,则返回locals())
from importlib import import_module
modules_to_import = ['pyodbc', 'pymssql', 'turbodbc', 'ibmdbpy.base.IdaDataBase']
for m in modules_to_import:
try:
globals()[m.split('.')[-1]] = import_module(m)
except ModuleNotFoundError:
print('Module {} not found'.format(m))