Python重构:清理导入

Python重构:清理导入,python,import,refactoring,Python,Import,Refactoring,这可能是一个新手类型的问题(我是从php5oo开始研究python的),但在尝试清理和重构一些python模块时,我对import语句有一些不确定的地方 比如说,我有一个db连接工厂模块,它导入mysqldb,如下所示: import MySQLdb as mysql from MySQLdb import cursors class ConnectionFactory(): @staticmethod def connect(db_host,db_user,db_pass,db,cur

这可能是一个新手类型的问题(我是从php5oo开始研究python的),但在尝试清理和重构一些python模块时,我对
import
语句有一些不确定的地方

比如说,我有一个db连接工厂模块,它导入mysqldb,如下所示:

import MySQLdb as mysql
from MySQLdb import cursors
class ConnectionFactory():
  @staticmethod
  def connect(db_host,db_user,db_pass,db,cursor='DictCursor'):
    connection = mysql.connect(host = db_host,
                   user = db_user,
                   passwd = db_pass,
                   db = db,
                   cursorclass=getattr(mysql.cursors, cursor))
    cur = connection.cursor();
    connection.ping(True)
    return (cur,connection)
首先,为什么第二个导入,即显式获取
游标的导入是必要的?如果没有它,我似乎无法直接访问mysql.cursors

另外,假设另一个模块导入此模块以获得db连接,然后使用它执行查询

import ConnectionFactory
def runquery(q):
  try:
    cur,connection = ConnectionFactory.connect(db_host,db_user,db_pass,db)
    cur.execute(q)
    res = cur.fetchall()
    return res
  except Exception as e:
    log(str(e))
理想情况下,捕获的异常应该是MySQLdb.Error异常这是否意味着我也需要在这里导入MySQLdb?我认为有一种更优雅的方法可以实现这一点。我敢肯定,我的思维方式不像蟒蛇

最后,假设这两个模块都导入到另一个父模块中,用于WSGI(我的所有内容都是通过Werkzeug实现的,Werkzeug随后在其他模块中运行大量其他方法)

如果WSGI同时导入这两个模块,我假设它们单独导入的内容不在其名称空间中如果最终要在一个较大的模块中同时使用相同的导入,那么在多个模块中使用相同的导入是否是一种不好的做法?

编辑:为了澄清第三个问题, 我有一个特殊的json编码器,它被广泛用作
cls
arg,用于
json.dumps()

gnengine
是我的WSGI,而
searchresult
是在该模块中找到的一种类型。我在这里导入它是因为它有自己的json方法,这是我的编码器所需要的。但是这种编码器显然也是为了在
gnengine
中使用而进口的。它们基本上是相互输入的

我的PHP背景告诉我,如果
searchresult
类型成为自己的表示对象模型的模块,然后两者分别导入,那么这一切都可以解决。但我不确定这是否是一个很大的误解

很抱歉将三个问题打包在一个问题中,基本上我猜被问到的是关于一般进口的澄清。我得到了名称空间,为什么从name import*
得到
是个坏主意,我只是不明白当几个包一起使用时,它们都有相似的依赖关系时,最好的方法是什么。在python中是否希望在整个过程中插入相同的
import
s

  • 我相信
    MySQLdb.cursors
    是另一个模块,嵌套模块必须单独导入

  • 如果您想特别捕获在
    MySQLdb
    中声明的异常,那么是的,您必须导入一些内容。如果要捕获任何异常,则不必导入但这可能不可取,正如@tkone在下面的评论中解释的那样。无论如何,我看不出从
    MySQLdb
    导入什么东西有什么问题——如果您的数据库访问代码不是分布在多个模块上,而是集中在(比如)数据库访问层,那么从
    MySQLdb
    导入的模块就不会太多

  • 我不确定我是否理解这个问题。你能澄清一下吗

  • MySQLdb的
    \uuuu init\uuuuu.py
    (或其他实例化机制)不导入游标,因此MySQLdb不知道游标模块,因为它“只是”它自己直接下的一个子目录。这意味着您需要显式导入它

  • 您需要直接从MySQLdb导入异常。类似于MySQLdb导入异常中的
    。异常只是扩展类的子类。Python不能对它不知道的类做任何事情。这里使用“from”术语仅导入所需的零件

  • 没有。将相同的对象导入到一堆不同的文件中,最终所有这些文件都能协同工作,这就是Python的工作方式。解释器确保不会影响运行时或重写任何内容,等等(请尝试连续两次导入相同的内容——没有错误,并且只得到一个实例)


  • 谢谢你的帮助!编辑以澄清#3。在我自己重读后,似乎有些模糊。第二点:你不应该使用
    ,除非:
    ,因为你会得到意想不到的副作用。例如,假设您正在try块中使用一个列表,如果您试图访问该列表上的不存在索引,您将得到一个
    索引器
    ,您应该以不同于MySQLdb异常的方式处理它。@tkone这就是我试图避免的,并将捕获更改为一个真正的mysql异常,这样我就可以在尾部添加一个通用的异常,只是不清楚如何在命名空间中获取特定于mysql的异常。非常好。是的,您还需要显式导入您的异常。谢谢!知道这些都很好,特别是#3,我实际上没有尝试过。为了澄清第3点,现在您已经更新了。这似乎是一个循环导入,只要您“做得对”,Python就可以处理它。参见:啊,太好了!当我第一次去FAQ的时候,我错过了一些关于循环的内容。实际上,我最后问这个问题是因为from命名的import语句以这种循环方式失败了,这使我首先认为我在做一些违背实践的事情。
    from datetime import datetime
    import gnengine
    import json
    
    class SpecialEncoder(json.JSONEncoder):
        def default(self,obj):
        if isinstance(obj,set):
            return list(obj)
        elif isinstance(obj,datetime):
            return obj.isoformat()
        elif isinstance(obj,gnengine.searchresult):
            return obj.jsonify()
    
        return json.JSONEncoder.default(self,obj)