在python中控制导入可选/额外库

时间:2019-05-05 00:46:07

标签: python import module

Setuptools允许您定义其他依赖项。您如何可以选择导入这些内容?

作为示例,考虑一个数据库包装器,它可以为无数个数据库提供某些功能

setup.py

extras_require={
    'postgres': ['postgresLibrary'],
    'mysql': ['mysqlLibrary'],
    ...
},

类定义

import postgresLibrary  <--- these imports will fail if extras not installed
import mysqlLibrary     


class DB:
    def __init__(self, db_type):
        if db_type == 'postgres':
            self.conn = PostgresConnection()
        elif db_type == 'mysql':
            self.conn == MySQLConnection()
        ...

setup.py可能允许最终用户有选择地安装他们选择的数据库库,但是我不清楚有选择地导入库的最佳方法是什么。我不愿意将它们导入到函数或构造函数中,但是除了要求最终用户安装他们可能不需要/不需要的所有库之外,我别无其他选择。

2 个答案:

答案 0 :(得分:1)

这是python中少数几个我认为单例设计模式可能有用的情况之一-作为选择性地将全局变量保留在内存中的机制。例如,代替

import postgresLibrary
import mysqlLibrary

您将创建一个类来跟踪当前导入的模块,并且只有 try 才能在首次使用它们时将其导入。例如,文件singleton.py

class SingletonBase:
    def __init__(self):
        self._modules = {}
    def __getattr__(self, module_name):
        if not module_name in self._modules:
            self._modules[module_name] = __import__(module_name)
        return self._modules[module_name]

Singleton = SingletonBase()

然后,您可以按照以下步骤进行操作,在本地使用postgresLibrary

from singleton import Singleton as S
...
postgresLibrary = S.postgresLibrary.PostgresConnection()

答案 1 :(得分:0)

有点hack,但是一个选择是将导入内容包装在try / except块中。如果postgres库不可用,并且用户尝试使用postgres的db_type初始化db对象,则可能引发异常,然后丢失导入。

我的原始答案不起作用,但我将其保留在此处,以便使注释有意义。

一种方法是为每种类型的数据库创建一个类。主数据库类不需要可选的导入,而postgres db类将需要postgres库,但不需要mysql库。

class DB:
    def __init__(self, db_type):
        if db_type == 'postgres':
            self.db = PostgresDB()
        elif db_type == 'mysql':
            self.db == MySQLDB()
        ...
   def get_connection(self):
        return self.db.conn

import postgresLibrary
class PostgresDB:
    def __init__(self):
    self.conn = PostgresConnection