Python脚本能在bash脚本内执行函数吗?

19 投票
3 回答
18180 浏览
提问于 2025-04-16 16:37

我有一个由第三方提供的bash脚本,这个脚本里定义了一些函数。下面是这个脚本的一个模板:

$ cat test.sh

#!/bin/bash

define go() {
    echo "hello"
}

我可以在bash命令行中这样调用go()函数:

$ source test.sh
$ go
hello

有没有办法从Python脚本中访问同样的函数呢?我试过以下方法,但没有成功:

Python 2.6.6 (r266:84292, Sep 15 2010, 15:52:39) 
[GCC 4.4.5] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> import subprocess
>>> subprocess.call("source test.sh")
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/usr/lib/python2.6/subprocess.py", line 470, in call
    return Popen(*popenargs, **kwargs).wait()
  File "/usr/lib/python2.6/subprocess.py", line 623, in __init__
    errread, errwrite)
  File "/usr/lib/python2.6/subprocess.py", line 1141, in _execute_child
    raise child_exception
OSError: [Errno 2] No such file or directory
>>> 

3 个回答

1

不,这个函数只能在那个bash脚本里使用。

你可以修改这个bash脚本,检查有没有传入参数,如果传入了特定的参数,就执行相应的函数。

比如说:

# $1 is the first argument

case $1 in
 "go" )
       go
       ;;
 "otherfunc" )
       otherfunc
       ;;
 * )
       echo "Unknown function"
       ;;
esac 

这样你就可以像这样调用这个函数:

subprocess.call("test.sh otherfunc")
2

这是基于@samplebias的解决方案,不过我做了一些修改,让它对我有效。

所以我把它封装成了一个函数,这个函数可以加载bash脚本文件,执行里面的bash函数,并返回结果。

def run_bash_function(library_path, function_name, params):
    params = shlex.split('"source %s; %s %s"' % (library_path, function_name, params))
    cmdline = ['bash', '-c'] + params
    p = subprocess.Popen(cmdline,
                         stdout=subprocess.PIPE, stderr=subprocess.PIPE)
    stdout, stderr = p.communicate()
    if p.returncode != 0:
        raise RuntimeError("'%s' failed, error code: '%s', stdout: '%s', stderr: '%s'" % (
            ' '.join(cmdline), p.returncode, stdout.rstrip(), stderr.rstrip()))
    return stdout.strip()  # This is the stdout from the shell command
43

是的,间接地可以。假设有这个foo.sh文件:

function go() { 
    echo "hi" 
}

试试这个:

>>> subprocess.Popen(['bash', '-c', '. foo.sh; go'])

输出结果:

hi

撰写回答