2016-01-01 7 views
7

Beispiel:Ist es möglich, Funktionen in der Shell von Python definiert zu verwenden?

#!/bin/bash 

function my_test(){ 
    echo this is a test $1 
} 

my_test 1 

python -c "from subprocess import check_output; print(check_output('my_test 2', shell=True))" 

Ausgang:

this is a test 1 
/bin/sh: my_test: command not found 
Traceback (most recent call last): 
    File "<string>", line 1, in <module> 
    File "/usr/lib/python3.5/subprocess.py", line 629, in check_output 
    **kwargs).stdout 
    File "/usr/lib/python3.5/subprocess.py", line 711, in run 
    output=stdout, stderr=stderr) 
subprocess.CalledProcessError: Command 'my_test 2' returned non-zero exit status 127 
+0

Warum nicht 'my_test' -Funktion in einer separaten Shell-Datei speichern und' python -c' mit diesem Shell-Skript-Aufruf von einem anderen ausführen? – vrs

+1

'/ bin/sh' unterstützt das Schlüsselwort' function' nicht. Verwende '#!/Bin/bash' (oder eine andere Shell) für deinen Shebang. – chepner

+0

Darf ich fragen, warum möchten Sie eine Funktion aufrufen, die nur in dieser Shell definiert ist? – nacho4d

Antwort

9

Sie müssen die Shell-Funktion exportieren, so wird es von Kind Schalen vererbt werden.

#!/bin/sh 

function my_test(){ 
    echo this is a test $1 
} 

my_test 1 

export -f my_test 
python -c "from subprocess import check_output; print(check_output('my_test 2', shell=True))" 
+0

Danke, das funktioniert, aber ich frage mich, ob es eine Möglichkeit gab, es von Python zu erben, ohne das Shell-Skript zu berühren. Ich schätze, das ist nicht möglich, oder? – orestisf

+0

Können Sie die Funktion in ein anderes Skript einfügen? Dann können Sie 'source scriptname' verwenden, bevor Sie versuchen, die Funktion aufzurufen. – Barmar

+0

Python weiß nichts über Shell-Skripte oder Funktionen. Es teilt der Shell nur mit, dass sie den Befehl ausführen soll. Wenn sich die Funktion nicht in der Shell-Umgebung befindet, kann sie nicht ausgeführt werden. Also musst du etwas tun, um es in die Umgebung zu bringen. – Barmar

0

Sie können das os-Modul verwenden.

import os 
os.system("anything what you would like to do in the shell") 
+0

Ich sehe nicht, wie dies hilft 'python -c" importieren os; print (os.system ('mein_test 2')) "' gibt immer noch 'sh aus: mein_test: befehl nicht gefunden' – orestisf

-2

Das OS-Modul ist definitiv der einfachste Weg und verursacht keine großen Probleme in einer Shell.

2

Beim Exportieren einer Funktion, die nicht von allen Shells unterstützt wird, wird der Code in den Umgebungsblock geschrieben. Dies ist ein sprachneutraler Block von Text, der bei der Erstellung eines neuen Prozesses von Parent nach Child kopiert wird.

Dies war die Basis von .

Das Problem ist, dass die beiden Sprachen Bash und Python völlig verschieden sind, so dass eine in einem geschriebene Funktion nicht direkt vom anderen ohne Übersetzung ausführbar ist. Der untergeordnete Prozess könnte den Umgebungsblock nach der Funktion durchsuchen, ihn dann übersetzen und in seine eigene Sprache übersetzen. Eine Menge Arbeit und könnte leicht ein Sicherheitsproblem sein.

Wenn Sie nur Bash-> Python-> Bash gehen wollen, dann sollten Sie die Funktion aus dem ersten Bash-Skript exportieren, da sie in jeden Umgebungsblock kopiert wird. Sie geben jedoch auch in einem Kommentar an, dass das erste Skript es nicht exportieren soll.

Nun, Sie könnte den Funktionscode lesen Python in eine Textzeichenfolge verwenden, dann legen Sie sie in die Umwelt selbst blockieren (das ist, was export tut in der Schale). Verwenden Sie das os.environ Wörterbuch.

Der tatsächlich verwendete Name hängt von Ihrer Version von Bash ab. Die ShellShock-Sicherheitslücke hat viele Änderungen zur Folge gehabt. Am besten erstellen Sie eine Testfunktion, exportieren Sie sie und verwenden Sie dann env, um den vollständigen Namen zu finden. Zum Beispiel erscheint in meiner Version eine einfache Funktion namens gash im Umgebungsblock als BASH_FUNC_gash%%.

BASH_FUNC_gash%%=() { echo 'Hollow world' 
} 

Zum Beispiel:

import os 
import subprocess 

fun_body="""() { echo 'Hollow world' 
} 
""" 
os.environ['BASH_FUNC_gash%%'] = fun_body 

p1 = subprocess.Popen('./myscript.sh') 

p1.wait() 

Das Skript (myscript.sh) enthält:

#!/bin/bash 
gash 

Alternativ Sie wieder auf Ihr Design aussehen könnte. Das Mischen von Sprachen ist immer problematisch. Warum schreiben Sie nicht alles in Python?

Verwandte Themen