Python中实现的可移植命令执行语法

时间:2009-08-08 15:38:42

标签: python shell cross-platform command

定义要运行的命令集中,Python不是一个很好的语言。巴什是。但Bash在Windows上并不天真。

背景:我正在尝试在mac / win / linux上构建一组程序 - 它们之间建立了依赖关系。像macport这样的东西,但应该在列出的所有三个平台上工作。

这需要有一个类似shell的语言,可用于定义命令序列以运行构建/修补/等特定程序,例如:

post-destroot {
    xinstall -d ${destroot}${prefix}/share/emacs/${version}/leim
    delete ${destroot}${prefix}/bin/ctags
    delete ${destroot}${prefix}/share/man/man1/ctags.1
    if {[variant_isset carbon]} {
        global version
        delete ${destroot}${prefix}/bin/emacs ${destroot}${prefix}/bin/emacs-${version}
    }
}

以上内容来自emacs Portfile in macports。注意使用变量,条件,函数..除了指定一个简单的命令列表,按顺序执行。

虽然语法不是Python,但实际的执行语义必须使用子进程或其他任何东西推迟到Python。简而言之,我应该能够“运行”这样的脚本..但是对于每个命令,调用指定的钩子函数,它实际上运行作为参数传递的任何命令。我希望你明白这一点。

3 个答案:

答案 0 :(得分:2)

听起来您需要PyParsingPython Subprocess的某种组合。

我发现子进程有点令人困惑,尽管它有MOTW,所以我经常使用这种包装代码。

from subprocess import Popen, PIPE

def shell(args, input=None):
    p = Popen(args, stdin=PIPE, stdout=PIPE, stderr=PIPE)
    stdout, stderr = p.communicate(input=input)
    return stdout, stderr

答案 1 :(得分:1)

Ned Batchelder在this post中列出了几十种不同的工具,您可以选择在Python中使用某种任意语言进行解析(尽管我不太明白为什么您不想使用Python它本身就是你“定义一组命令来运行的语言”,我相信你有自己的理由)。 Ned列出的这些工具之一就是Gregg所提到的pyparsing,但是还有超过三十个其他工具,所以你可能想要在你选择一个符合你口味的产品之前先看看。

将输入源语言转换为语法树或其他方便的内存中表示后,您可以直接遍历树并执行(插入变量值,在条件和循环上分支等)。除了运行外部进程的能力(例如通过子进程,无论是否包含在Gregg建议中),不要忘记Python本身可以执行一些基本命令而不会出汗,并且,如果可行的话,这比将执行委托给子进程要快得多(事实上,Perl成功的一个早期动机是它可以在一个进程中做很多事情,而sh就像疯了一样离开;像bash和ksh这样的现代后代上了课,现在实现了许多可以在与主脚本相同的过程中执行的内置函数; - )。

例如,您的示例中的delete命令可以通过os.unlink“内部”实现(由于HW问题,python.org目前已关闭,因此无法立即链接到Python在线文档; - 。)

答案 2 :(得分:0)

这是我的琐碎建议:通过regexp将其解析为Python,使其成为

def post_destroot():
    xinstall ('-d', '${destroot}${prefix}/share/emacs/${version}/leim')
    delete ('${destroot}${prefix}/bin/ctags')
    delete ('${destroot}${prefix}/share/man/man1/ctags.1')
    if test('variant_isset', 'carbon'):
        global('version')
        delete('${destroot}${prefix}/bin/emacs', '${destroot}${prefix}/bin/emacs-${version}')

我认为编写xinstall()delete()test()函数并不困难,特别是因为Python已经有内置函数来格式化字符串"{destroot}".format(dictionary).

但为什么要这么麻烦?尝试从标准库中查看distutils模块。