如何在没有大量手动编辑的情况下,在很多文件中用另一个模块替换另一个类的类?

时间:2009-11-04 16:02:31

标签: python automation sed rope

基本上,我有一个很多的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的所有实例。我可以接受输入in,所以这也没关系:

from foo import a, b, c
from baz import foobar

class bar(object):
    x = foobar()
    y = b()
    z = c()

对此进行sed s/xyz/foobar/似乎微不足道,但是我仍然需要返回并更改import语句。我做一些手工工作很好,但我想学习新的方法来减少它的数量。

那你怎么做这个改变?有什么我可以做sed这样做吗?或绳索(我没有看到任何明显的东西可以帮助我在这里)?

5 个答案:

答案 0 :(得分:3)

猴子修补将是快速而肮脏的方式 - 在进行任何其他导入之前,执行以下初步:

import foo
import baz
foo.a = baz.m

现在,模块a的属性foo的每次后续使用实际上将根据需要使用模块m的类baz,而不是原始类{{ 1}}模块a。不是特别干净,但可能非常有效。只需要确保在任何其他导入之前进行猴子修补(您还可以在整个对象图中追逐以找到在修补之前放置到foo的每个引用,并将其更改为foo.a ,但那方式更重,更棘手)。

答案 1 :(得分:1)

因为bar会被改为bmr,所以sed s / a / m会很灾难。

如果变量名称真的很短和/或非唯一,则不可正则, 那么也许最容易做的就是插入

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

也可以,因为上次导入获胜。

答案 2 :(得分: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

T中的sed命令分支到标签(如果没有给出标签,则为结尾),如果没有进行替换。在此示例中,“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

答案 3 :(得分:0)

我没有使用绳索,但你不能移动到baz然后重命名baz.a到baz.m你可以在其他语言的其他重构工具和rope page建议它可以。

对于最小的编辑 - 但可能更差的风格和可维护性使foo.a调用baz.m

答案 4 :(得分:0)

我不会使用monkeypatching,我会实现自己的功能:

import foo

def xyz():
    return foo.xyz()

def b():
    return foo.b()

def c():
    return foo.c()

现在我可以更改xyz()以使其执行任何我想要的操作,如果我想明确调用foo.xyz(),我可以。

此外,如果我将该代码粘贴到模块中,我可以在目前使用from foo import的所有模块中全局替换from my_foo import foo