4

这个问题我想了很久,一直没搞明白,希望各位大神帮忙。

我有一个 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 文件都可以只是中间的代码。但是,普通模块在这里不起作用(除非我弄错了),因为我会从争论中得到我需要执行的代码,这将是一个字符串,因此我不知道要运行哪个函数直到运行时.

所以我想出了另外两个解决方案:

  1. 我可以编写一堆 if 语句,一个基于某个参数运行每个脚本。我拒绝了这个,因为它比以前的设计更糟糕。
  2. 我可以使用:

    os.command(sys.argv[0] scriptName.py)

    这将运行脚本,但调用 python 来调用 python 对我来说似乎不是很优雅。

那么有人有其他想法吗?谢谢你。

4

6 回答 6

4

如果您知道函数的名称为字符串,模块的名称为字符串,那么您可以这样做

mod = __import__(module_name)
fn = getattr(mod, fn_name)
fn()
于 2010-08-07T23:51:09.287 回答
4

另一种可能的解决方案是让每个重复文件从主文件中导入功能

from topAndBottom import top, bottom
top()
# do middle stuff
bottom()
于 2010-08-08T00:48:34.857 回答
2

除了已经发布的几个答案之外,请考虑模板方法设计模式:制作一个抽象类,例如

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它),但仍然值得牢记(连同它的许多 Pythonic 变体,我已经在许多现在可以在 youtube 上获得技术讲座)用于“可插拔部件”的数量或复杂性不断增长的情况——模板方法(尽管它的名字很可怕;-)是一种可靠的、经过充分验证且高度可扩展的模式 [[有时也有点僵化的,但这正是我在许多技术会谈中所要解决的问题——而且这个问题不适用于这个特定的用例]]。

于 2010-08-08T02:40:06.060 回答
0

但是,普通模块在这里不起作用(除非我弄错了),因为我会从争论中得到我需要执行的代码,这将是一个字符串,因此我不知道要运行哪个函数直到运行时.

它会工作得很好 - 使用__import__内置的,或者,如果你有非常复杂的布局,使用imp模块来导入你的脚本。然后您可以通过module.__dict__[funcname]例如获取该功能。

于 2010-08-07T23:52:01.297 回答
0

导入模块(如其他答案中所述)绝对是更清洁的方法,但如果由于某种原因不起作用,只要你没有做任何太奇怪的事情,你就可以使用exec. exec它基本上运行另一个文件的内容,就好像它在调用点包含在当前文件中一样。这是 Python 最接近source许多 shell 中包含的那种语句的东西。作为最低限度,这样的事情应该可以工作:

exec(open(filename).read(None))
于 2010-08-08T00:43:26.763 回答
0

这个怎么样?

function do_thing_one():
   pass

function do_thing_two():
   pass

dispatch = { "one" : do_thing_one,
             "two" : do_thing_two,
           }

# do something to get your string from the command line (optparse, argv, whatever)
# and put it in variable "mystring"

# do top thing
f = dispatch[mystring]
f()
# do bottom thing
于 2010-08-08T02:06:08.347 回答