热插拔Python代码(鸭子类型函数?)
我考虑这个问题已经很久了,但一直没有头绪,也许你们中的一些人可以帮我。
我有一个文件夹,里面放着一些Python脚本,这些脚本的结构基本上是一样的(实际上,我是通过一个shell脚本生成的),但有一部分代码是不同的。换句话说:
Top piece of code (always the same)
Middle piece of code (changes from file to file)
Bottom piece of code (always the same)
我今天意识到这样做其实不太好,比如说,如果我想修改顶部或底部的某些内容,我就得写一个shell脚本来完成。(虽然这并不难,但从代码的角度来看,这样做似乎很糟糕)。
所以我想要做的是,写一个外部的Python脚本,结构像这样:
Top piece of code
Dynamic function that calls the middle piece of code (based on a parameter)
Bottom piece of code
然后文件夹里的其他Python文件就可以只包含中间那部分代码。不过,普通的模块在这里可能不太适用(除非我搞错了),因为我需要从参数中获取要执行的代码,而这个参数是一个字符串,这样我在运行时就不知道该运行哪个函数了。
因此,我想到了另外两个解决方案:
- 我可以写一堆if语句,根据某个参数来运行每个脚本。但我觉得这个方法比之前的设计还要糟糕。
我可以使用:
os.command(sys.argv[0] scriptName.py)
这样可以运行脚本,但用Python去调用另一个Python脚本在我看来并不是很优雅。
所以有没有其他的想法呢?谢谢大家。
6 个回答
除了已经发布的几个答案外,还可以考虑一下模板方法设计模式:可以创建一个抽象类,比如
class Base(object):
def top(self): ...
def bottom(self): ...
def middle(self): raise NotImplementedError
def doit(self):
self.top()
self.middle()
self.bottom()
然后每个可插拔的模块都会创建一个类,继承这个Base
类,并且必须重写middle
方法,填入相关的代码。
虽然在这个简单的例子中可能不太必要(你仍然需要导入正确的模块,以便实例化它的类并调用doit
方法),但在“可插拔部分”的数量或复杂性不断增加的情况下,记住这个方法还是很有价值的。模板方法(尽管名字听起来不太好;-) 是一个可靠、经过验证并且高度可扩展的模式[[有时可能会有点过于严格,但我在许多现在可以在YouTube上找到的技术讲座中详细讨论了这个问题——而这个问题并不适用于这个特定的使用案例]]。
另一种可能的解决办法是让你那些重复的文件从主文件中导入功能。
from topAndBottom import top, bottom
top()
# do middle stuff
bottom()
如果你知道一个函数的名字和一个模块的名字都是以字符串的形式存在,那么你可以这样做:
mod = __import__(module_name)
fn = getattr(mod, fn_name)
fn()