可选导入的pythonic方法

时间:2018-10-15 23:33:08

标签: python import

我有一个软件包,允许用户使用要连接到数据库的4个软件包中的任何一个。效果很好,但我对导入的方式不满意。

我可以简单地导入所有软件包,但是如果特定用户不需要使用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

这感觉不像pythonic。因此,我知道有诸如holoviews或tensorflow之类的软件包可以让您指定后端。当然,它们比我的复杂了几个数量级,但它们必须处理相同的模式。

如何正确编写此代码?从技术上讲,这是有问题的,因为如果他们打算使用pyodbc但没有安装,我的程序将不会警告他们,它将在运行时出错。因此,这确实超出了美学或哲学范围;这是技术上容易出错的代码。

您将如何处理这种情况?

好,下面是代码调用示例:

connect('Playground', package='pymssql')

4 个答案:

答案 0 :(得分:2)

try: import pyodbc
except ImportError: pyodbc = None

然后再     如果pyodbc为None且user_wants_to_use_pyodbc为:         print_warning         引发SomeConfigurationErrorOrSuch

这种方法对于少数选项非常有效。如果您有足够的选择需要抽象出这种方法,则可以使用importlib模块在​​程序的控制下导入模块。

答案 1 :(得分:2)

我将使用importlib中的import_module:

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))

答案 2 :(得分:1)

您可以将导入放置在文件开头之外的其他位置。 “重新导入”实际上并没有任何作用,因此频繁import 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()

答案 3 :(得分:1)

我使用了与上述答案类似的方法,但我不认为有时您可能需要模拟一个对象来欺骗 lint。

try:
    from neuralprophet import NeuralProphet
    using_neuralprophet = True
except ImportError:
    class NeuralMock:
       whatever=False
    using_neuralprophet = False
    NeuralProphet = NeuralMock()

来源:timemachines