如何有效地修复";未定义的或从"imports"定义的;当加载"警告"



我有超过40个文件的遗留代码,这些文件使用from variables import *语法从主"variables.py"文件导入变量。此导入导致我的IDE(Spyder(对value = variable + 1等行发出类似"未定义,或从*imports定义"的警告我知道最好在导入中明确命名变量,并希望有效地解决问题

是否有一种有效的方法来修复多个文件中的这些警告,这些文件中有许多变量是从这个主变量.py(包含>100个变量(导入的?还是最好浏览这些遗留文件,并在链接的帖子中明确命名变量?

一种风险较高的方法是自动化重构(我们稍后将定义风险(。我们将使用另一个Python脚本和re模块来完成这一壮举:

import re
# define all your critical variables here...
prefix = 'v'
pats = {
'var': r'^([wd_]+) =',
'cls': r'^class ([wd_]+)(',
'func': r'^def ([wd_]+)('
}
objs = []
file_lists = ['full path to py #1 for refactor', 'full path to py #2 for refactor', 'etc...']
file = 'variables.py'
path = 'some/path/to/the/variables.py/module'
# load the contents of variables.py
with open('/'.join((path, file)), 'r') as f:
lines = f.readlines()
# extract all the objects with known patterns from the module
for line in lines:
for pat in pats.values():
found = re.search(pat, line)
if found:
objs.append(found.group(1)) # return the extracted object name
# iterate through the files requiring refactor
for fl in file_lists:
with open(fl, 'r') as f:
codes = f.read()
# replace the star import with alias import
codes = re.sub(r'from {module} import *'.format(module=file.rstrip('.py')), 'import {module} as {pfx}'.format(module=file.rstrip('.py'), pfx=prefix), codes)
# replace each object with their aliased alternative
for obj in objs:
codes = re.sub(r'(b){var}(b)'.format(var=obj), r'1{pfx}.{o}2'.format(pfx=prefix, o=obj), codes)
# write to a NEW file, so you can compare and merge
with open(fl.replace('.py','_refactored.py'), 'w') as f:
f.write(codes)

最大的警告是,您在没有监督更改的情况下更改代码您可能希望添加一个logger,以便每次更改替换项时,都可以记录更改的内容和替换项。第二个最大的警告是,这并没有考虑到strings包含与变量匹配的内容。例如,如果你有一行"这是一个变量",并且你想替换objvariable,那么这次执行也会无意中更改string

因此,即使您打算完成此练习,最好在将其称为最终副本之前,先比较之前和之后的练习,并进行任何必要的修复。但它应该完成90%的手动工作。


这里有一个快速测试:

variables.py内容

class Bar():
pass
def func():
pass
test = 'hello'
foo = 'world'

codebase1.py:

from variables import *
# essentially they are:
test = 'something new'        # codebase1.test
Bar(test)                     # codebase1.Bar
func(foo)                     # codebase1.func
foo = 'Bar'                   # codebase1.foo

codebase1_refracted.py:

import variables as v
# essentially these are now:
v.test = 'something new'      # variables.test
v.Bar(v.test)                 # variables.Bar
v.func(v.foo)                 # variables.func
v.foo = 'v.Bar'               # variables.foo
# Note these are now directly referencing the objects within variables.py
# any reassignment/changes to these objects 
# will now have an impact on all other codebases
# that import from variables.py after the changes took place.
# Note also the string value for v.foo is also changed inadvertently.

编辑:

正如@user2357112所指出的,另一个警告是,这也将微妙地改变当前分配的行为方式。在星形导入的情况下,导入的对象(例如test(在即时代码的范围内,对对象的重新分配/更改不会影响variables.test的范围。然而,对于v.test,它确实直接干扰了variables.test对象,之后任何其他导入变量的代码都将读取新分配/更改的对象,而不是从variables.py读取。

相关内容

最新更新