2011-04-29 12 views
13

Tengo un script bash proporcionado por un tercero que define un conjunto de funciones. Aquí está una plantilla de lo que se ve como¿Puede un script de python ejecutar una función dentro de un script bash?

$ cat test.sh 

#!/bin/bash 

define go() { 
    echo "hello" 
} 

que pueda hacer lo siguiente desde un shell bash para llamar a ir():

$ source test.sh 
$ go 
hello 

¿Hay alguna manera de acceder a la misma función de un script en Python ? Intenté lo siguiente, pero no funcionó:

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 
>>> 
+4

¿Qué función tiene en 'bash' que no se puede duplicar en' Python'? – ghostdog74

Respuesta

32

Sí, indirectamente. Dada esta foo.sh:

function go() { 
    echo "hi" 
} 

Prueba esto:

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

Salida:

hi 
+1

Excelente, gracias! – Ravi

1

No, la función solo está disponible dentro de esa secuencia de comandos bash.

Lo que podría hacer es adaptar el script bash buscando un argumento y ejecutar funciones si se da un argumento específico.

Por ejemplo

# $1 is the first argument 

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

A continuación, puede llamar a la función como esta:

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

basado en la solución @samplebias pero con algunas modificaciones que trabajó para mí,

Así que lo envolví en una función que carga el archivo de script bash, ejecutivo utes función bash y devuelve la salida

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 
+2

Si está escribiendo una función para tomar parámetros arbitrarios, entonces debería usar 'shlex.quote'. – donkopotamus

+0

@donkopotamus Correcto, pero creo que 'shlex.split' hará el trabajo en ese caso, ¿no es así? es decir: 'shlex.split ('' source% s;% s% s" '% (library_path, function_name, params)) ' – Samuel

+0

No hay mención de' shlex.split' en su respuesta. En cualquier caso, 'shlex.split' no maneja las entradas de cotización. El punto es el siguiente ... ¿qué hará tu función si se llama con un nombre de función de 'blah; rm -rf/'? (No recomendaría que lo pruebes ...) – donkopotamus

Cuestiones relacionadas