如何从x import *替换为在python代码中导入x?

时间:2016-10-27 17:57:24

标签: python parsing pyqt abstract-syntax-tree sublime-text-plugin

我有一堆长pyqt脚本,其中原作者编写了这样的代码

from PyQt4.QtGui import *
from PyQt4.QtCore import *
...

是否有智能或快捷的方式将代码更改为

from PyQt4 import QtGui,QtCore
...

并为每个pyqt类添加模块名称前缀?例如 使用sublime编辑器或pycharm将QDialog更改为QtGui.QDialog?或任何其他编辑?

我读到可以为2to3脚本添加自定义修复程序,并为此重新使用该工具,但这似乎不是一项简单的任务。或者建造树木并自己做替换(声音更复杂,也许它正在重新发明轮子)。或者我应该只编写正则表达式替换脚本并解析所有.py文件? (听起来不安全)

编辑:我读了原始问题,似乎我的问题是它的一个子集,最后我使用了一个hacky解决方案,因为我知道我想修复的代码是pyqt。

bad_file = '/path/to/bad_file'
import re

from PyQt4 import QtCore,QtGui

QtCore_mappings = [x for x in dir(QtCore) if '_' not in x]
QtGui_mappings = [x for x in dir(QtGui) if '_' not in x]

mappings = {'QtCore':QtCore_mappings,'QtGui':QtGui_mappings }

cache={}


def find_class_long_name(c):
    for k,v in mappings.iteritems():
        if c in v:
            return '%s.%s' % (k,c)
    else:
        return None

with open(bad_file) as f:
    code = f.read()

    all_classes =  re.findall(r'\bQ[A-Z]\w*\b', code)
    all_classes=set(all_classes)

    for c in all_classes:
        new_c = find_class_long_name(c)
        if new_c:
            print '%s ---> %s' % (c, new_c)
            code=re.sub(r'\b%s\b' %c,new_c,code)
        else:
            print 'skipped:',c

        # write code to new file

更新2: 我想我可以在不更改代码的情况下替换模块导入行

def find_module(c):
    for k,v in mappings.iteritems():
        if c in v:
            return k
    else:
        return None

with open(bad_file) as f:
    code = f.read()
    # print code

    all_classes =  re.findall(r'\bQ[A-Z]\w*\b', code)
    all_classes=set(all_classes)

    for c in all_classes:
        c_module = find_module(c)
        if c_module:
            cache[c_module].append(c)
        else:
            print 'skipped:',c

    cmd = ''
    for k,v in cache.iteritems():
        if cache[k]:
            cmd+='from %s import (%s)' % (k, ', '.join(sorted(cache[k])))
            cmd+='\n'

    print 'new import:\n'
    print cmd

0 个答案:

没有答案