如何在多个文件中不进行大量手动编辑,替换一个类为另一个模块中的类?
基本上,我有很多Python类(这些类代表我们的数据库结构),它们看起来像这样:
from foo import xyz, b, c
class bar(object):
x = xyz()
y = b()
z = c()
...我想把它们改成这样:
from foo import b, c
from baz import foobar
class bar(object):
x = foobar()
y = b()
z = c()
简单来说,我就是想把所有的xyz
替换成foobar
。我觉得保留一个导入语句是可以的,所以这样也没问题:
from foo import a, b, c
from baz import foobar
class bar(object):
x = foobar()
y = b()
z = c()
用sed s/xyz/foobar/
来做这个看起来很简单,但我还得回去改导入语句。我可以接受做一些手动的工作,但我想学习一些新方法来减少这些工作量。
那么,你会怎么做这个更改呢?我能用sed做些什么吗?或者用rope(我没有看到有什么明显的办法可以帮我)?
5 个回答
1
你可以试试这个 sed
脚本:
sed -r 's/(^from foo import.*)(xyz, |, xyz)(.*)/\1\3/; T; a\from baz import foobar'
或者,等效的写法是:
sed 's/\(^from foo import.*\)\(xyz, \|, xyz\)\(.*\)/\1\3/; T; a\from baz import foobar'
如果你这样尝试,就会得到下面的结果:
$ echo "from foo import xyz, b, c"|sed -r 's/(^from foo import.*)(xyz, |, xyz)(.*)/\1\3/; T; a\from baz import foobar'
from foo import b, c
from baz import foobar
$ echo "from foo import b, xyz, c"|sed -r 's/(^from foo import.*)(xyz, |, xyz)(.*)/\1\3/; T; a\from baz import foobar'
from foo import b, c
from baz import foobar
$ echo "from foo import b, c, xyz"|sed -r 's/(^from foo import.*)(xyz, |, xyz)(.*)/\1\3/; T; a\from baz import foobar'
from foo import b, c
from baz import foobar
在 sed
中,T
命令会在没有进行替换时跳转到一个标签(如果没有标签,就跳到最后)。在这个例子中,“from baz”这一行只会被添加一次:
$ echo "from foo import d, e, f
from foo import xyz, b, c
from bar import g, h, i"|sed -r 's/(^from foo import.*)(xyz, |, xyz)(.*)/\1\3/;a\from baz import foobar'
from foo import d, e, f
from foo import b, c
from baz import foobar
from bar import g, h, i
1
用命令 `sed s/a/m` 来替换的话会很糟糕,因为这样会把 "bar" 变成 "bmr"。
如果变量名真的很短,或者不太独特,无法用正则表达式处理,那么最简单的方法可能就是插入
from baz import m as a
这样你就不需要去修改文件中其他地方的代码了。
你可以用 `sed` 来把
from foo import a,b,c
改成
from foo import b,c
不过
from foo import a,b,c
from baz import m as a
也可以这样做,因为最后导入的会覆盖之前的。
3
猴子补丁是一种快速但不太干净的方法。在你进行其他导入之前,先执行以下准备工作:
import foo
import baz
foo.a = baz.m
这样一来,之后每次使用模块 foo
的属性 a
时,实际上会使用模块 baz
的类 m
,而不是模块 foo
的原始类 a
。虽然这种方法不太优雅,但可能会非常有效。一定要确保猴子补丁是在其他导入之前进行的(你也可以遍历整个对象图,找到所有在补丁之前引用的 foo.a
,然后把它们改成 baz.m
,但这会复杂得多,也更麻烦)。