431 Stimmen

Ein Python-Skript von einem anderen Python-Skript aus ausführen, indem Argumente übergeben werden

Ich möchte ein Python-Skript von einem anderen Python-Skript aus ausführen. Ich möchte Variablen so übergeben, wie ich es über die Kommandozeile tun würde.

Ich würde zum Beispiel mein erstes Skript ausführen, das eine Liste von Werten (0,1,2,3) durchläuft und diese an das zweite Skript weitergibt script2.py 0 dann script2.py 1 , usw.

Ich fand Stack Overflow-Frage 1186789 was eine ähnliche Frage ist, aber die Antwort von ars ruft eine Funktion auf, während ich das ganze Skript ausführen möchte, nicht nur eine Funktion, und die Antwort von balpha ruft das Skript auf, aber ohne Argumente. Ich habe dies testweise in etwas wie das Folgende geändert:

execfile("script2.py 1")

Aber die Variablen werden nicht richtig akzeptiert. Wenn ich den Ausdruck sys.argv in script2.py ist es der ursprüngliche Befehlsaufruf des ersten Skripts "[' C:\script1.py '].

Ich möchte das ursprüngliche Skript (d. h. script2.py in meinem Beispiel) nicht wirklich ändern, da ich es nicht besitze.

Ich denke, es muss einen Weg geben, dies zu tun; ich bin nur verwirrt, wie Sie es tun.

419voto

Greg Hewgill Punkte 882617

Versuchen Sie es mit os.system :

os.system("script2.py 1")

execfile ist anders, denn es ist so konzipiert, dass es eine Folge von Python-Anweisungen in der aktuell Ausführungskontext. Deshalb ist sys.argv hat sich für Sie nicht geändert.

138voto

Katriel Punkte 115208

Das ist von Natur aus falsch. Wenn Sie ein Python-Skript von einem anderen Python-Skript aus ausführen, sollten Sie über Python und nicht über das Betriebssystem kommunizieren:

import script1

In einer idealen Welt können Sie eine Funktion innerhalb von script1 direkt:

for i in range(whatever):
    script1.some_function(i)

Falls erforderlich, können Sie Folgendes hacken sys.argv . Um sicherzustellen, dass Sie keine dauerhaften Änderungen vornehmen, gibt es eine elegante Methode, dies mit einem Kontextmanager zu tun.

import contextlib
@contextlib.contextmanager
def redirect_argv(num):
    sys._argv = sys.argv[:]
    sys.argv=[str(num)]
    yield
    sys.argv = sys._argv

with redirect_argv(1):
    print(sys.argv)

Ich denke, das ist besser, als alle Daten an das Betriebssystem und wieder zurück zu übertragen; das ist einfach nur dumm.

138voto

kindall Punkte 167554

Im Idealfall enthält das Python-Skript, das Sie ausführen möchten, am Ende einen Code wie diesen:

def main(arg1, arg2, etc):
    # do whatever the script does

if __name__ == "__main__":
    main(sys.argv[1], sys.argv[2], sys.argv[3])

Mit anderen Worten, wenn das Modul von der Befehlszeile aus aufgerufen wird, analysiert es die Befehlszeilenoptionen und ruft dann eine andere Funktion auf, main() um die eigentliche Arbeit zu erledigen. (Die tatsächlichen Argumente werden variieren, und das Parsing kann aufwändiger sein).

Wenn Sie jedoch ein solches Skript von einem anderen Python-Skript aus aufrufen wollen, können Sie einfach import es und rufen Sie modulename.main() direkt, anstatt über das Betriebssystem zu gehen.

os.system wird funktionieren, aber es ist der Umweg (lesen Sie "langsam") zu tun, da Sie eine ganz neue Python-Interpreter-Prozess jedes Mal für keine raisin starten.

63voto

Medhat Punkte 1474

Ich denke, die gute Praxis könnte in etwa so aussehen;

import subprocess
cmd = 'python script.py'

p = subprocess.Popen(cmd, stdout=subprocess.PIPE, shell=True)
out, err = p.communicate() 
result = out.split('\n')
for lin in result:
    if not lin.startswith('#'):
        print(lin)

nach der Dokumentation Das Modul subprocess ermöglicht es Ihnen, neue Prozesse zu starten, sich mit ihren Eingabe-/Ausgabe-/Fehlerleitungen zu verbinden und ihre Rückgabewerte zu erhalten. Dieses Modul soll mehrere ältere Module und Funktionen ersetzen:

os.system
os.spawn*
os.popen*
popen2.*
commands.*

Verwenden Sie communicate() anstelle von .stdin.write, .stdout.read oder .stderr.read, um Deadlocks zu vermeiden, die dadurch entstehen, dass einer der anderen OS-Pipe-Puffer sich füllt und den Kindprozess blockiert. Hier lesen

53voto

Chris Adams Punkte 1017

Modul SubProzess:
http://docs.python.org/dev/library/subprocess.html#using-the-subprocess-module

import subprocess
subprocess.Popen("script2.py 1", shell=True)

Damit können Sie auch stdin, stdout und stderr umleiten.

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X