如何在没有大量手动编辑的情况下,用许多文件中的其他模块替换另一个类的类?
基本上,我有一个看起来像这样的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()
本质上,我只是想用foobar
替换xyz
的所有实例。这是可以接受的我离开的的进口,所以这也将是罚款:
from foo import a, b, c
from baz import foobar
class bar(object):
x = foobar()
y = b()
z = c()
看来微不足道的做这个sed s/xyz/foobar/
,但我还是不得不回去改进口声明。我在做一些手工工作时很好,但我想学习新的方法来减少它的数量。
那么你会如何做这个改变?有什么我可以用sed来做到这一点?或绳子(我没有看到任何明显的东西可以帮助我)?
因为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
将工作太,自上次进口的胜利。
猴补丁将是快速和肮脏的方式做到这一点 - 你做任何其他进口之前,执行以下初步:
import foo
import baz
foo.a = baz.m
现在,每一个后续使用模块foo
的属性a
的实际上是使用模块baz
的m
类,如需要,而不是模块foo
原a
类。不是特别干净,但可能相当有效。只要确保猴子补丁发生在任何其他导入之前(您也可以在整个对象图中追踪找到在修补前已放置到位的所有参考,并将其更改为baz.m
,但这是方式较重并且麻烦)。
不幸的是,我仍然需要在几个地方使用a。由于foo是第三方库,我有点犹豫要做更多的诡计来解决这个问题。 – 2009-11-04 16:19:31
@Jason,很好啊 - 也许你可以在需要的地方“反转monkeypatch”foo的原始a(你可以明显地藏在一旁,然后再重新分配)。否则,它肯定可以通过修改代码来实现,但方式更复杂(除非名称无误,因为您似乎用编辑来指示xyz而不是;-)。 – 2009-11-05 01:09:56
你可以试试这个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
命令分支到一个标签(如果不是标签被给出)如果没有进行替换。在这个例子中,“从巴兹”行只追加一次:
$ 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
我不会用的monkeypatching,我会实现自己的功能:
import foo
def xyz():
return foo.xyz()
def b():
return foo.b()
def c():
return foo.c()
现在我可以改变xyz()
到让它做我想做的任何事情,如果我想要明确地致电foo.xyz()
,我可以。此外,如果我将该代码粘贴到某个模块中,则可以在目前使用foo
的所有模块中全局替换from foo import
和from my_foo import
。
其实,它们比那个更独特(并且不太可能出现在其他地方)。为了简单起见,我只是使用'm'和'a'。 – 2009-11-04 16:09:31
我已经更新了页面,使它更清晰一点(虽然有点乳酪)。而sed方法不起作用,因为我可能会碰到'from foo import b,c,xyz'这样的东西。 – 2009-11-04 16:14:19