2009-04-30 1 views
16

Ich arbeite an einem Wrapper-Skript, das eine ausführbare vmware ausführen wird, die die Automatisierung der Start/Herunterfahren/Registrieren/Aufheben der Aktionen der virtuellen Maschine ermöglicht. Ich versuche Subprozess zu verwenden, um die ausführbare Datei aufzurufen, aber die Leerzeichen im ausführbaren Pfad und in den Parametern der ausführbaren Datei werden vom Subprozess nicht korrekt verarbeitet. Unten ist ein Codefragment:Wie Subprozess verwenden, wenn mehrere Argumente Leerzeichen enthalten?

vmrun_cmd = r"c:/Program Files/VMware/VMware Server/vmware-cmd.bat" 
def vm_start(target_vm): 
    list_arg = "start" 
    list_arg2 = "hard" 
    if vm_list(target_vm): 
      p = Popen([vmrun_cmd, target_vm, list_arg, list_arg2], stdout=PIPE).communicate()[0] 
      print p 
    else: 
      vm_register(target_vm) 
      vm_start(target_vm) 
def vm_list2(target_vm): 
    list_arg = "-l" 
    p = Popen([vmrun_cmd, list_arg], stdout=PIPE).communicate()[0] 
    for line in p.split('\n'): 
      print line 

Wenn ich die vm_list2 Funktion aufrufen, erhalte ich die folgende Ausgabe:

$ ./vmware_control.py --list             
C:\Virtual Machines\QAW2K3Server\Windows Server 2003 Standard Edition.vmx 
C:\Virtual Machines\ubunturouter\Ubuntu.vmx 
C:\Virtual Machines\vacc\vacc.vmx 
C:\Virtual Machines\EdgeAS-4.4.x\Other Linux 2.4.x kernel.vmx 
C:\Virtual Machines\UbuntuServer1\Ubuntu.vmx 
C:\Virtual Machines\Other Linux 2.4.x kernel\Other Linux 2.4.x kernel.vmx 
C:\Virtual Machines\QAClient\Windows XP Professional.vmx 

Wenn ich die vm_start Funktion aufrufen, die einen Weg zu vm Parameter erfordert, ich erhalte die folgende Ausgabe:

$ ./vmware_control.py --start "C:\Virtual Machines\ubunturouter\Ubuntu.vmx" 
'c:\Program' is not recognized as an internal or external command, 
operable program or batch file. 

Offenbar ist die Anwesenheit eines zweiten Parameters mit eingebetteten Leerzeichen wird, um die Art und Weise zu verändern, dass subprocess den ersten Parameter interpretiert. Irgendwelche Vorschläge, wie man das löst?

python2.5.2/Cygwin/winxp

+0

Warum sind Ihre Schrägstriche in c:/Programme/VMware/VMware Server/vmware-cmd. Fledermaus in die falsche Richtung gehen? Ist es nicht c: \ Programme \ ...? –

+2

Nun, Cygwin ist * Nix-Port, so scheint es, dass der Standard (oder was ich verstehe, um den Standard zu sein) * Nix-Schrägstrich-Notation Mein Verständnis ist, dass Subprozess das Trennzeichen zu was auch immer das zugrunde liegende System benötigt übersetzt. –

+0

hat es für jetzt gelöst? – Gohan

Antwort

-2

Warum Sie r verwenden ""? Ich glaube, dass wenn Sie das "r" von Anfang entfernen, wird es als eine Standardzeichenfolge behandelt, die Leerzeichen enthalten kann. Python sollte dann die Zeichenfolge korrekt angeben, wenn sie an die Shell gesendet wird.

+0

Ich habe dies überprüft, und der rohe String-Status ändert das Verhalten nicht. –

+2

macht Sinn, r zu verwenden " ... \ ... "für Windows-Dateinamen. –

4
'c:\Program' is not recognized as an internal or external command, 
operable program or batch file. 

Diese Nachricht zu erhalten, sind Sie entweder:

  1. shell=True Verwendung:

    vmrun_cmd = r"c:\Program Files\VMware\VMware Server\vmware-cmd.bat" 
    subprocess.Popen(vmrun_cmd, shell=True) 
    
  2. Wechsel auf anderen Teil des Codes vmrun_cmd

  3. immer diese Fehlermeldung aus etwas in vmware-cmd.bat

Dinge zu versuchen:

  • Öffnen Sie eine Python-Eingabeaufforderung den folgenden Befehl ausführen:

    subprocess.Popen([r"c:\Program Files\VMware\VMware Server\vmware-cmd.bat"]) 
    

Wenn das funktioniert, dann zitierte Themen sind indiskutabel. Wenn nicht, haben Sie das Problem isoliert.

+0

In dieser Reihenfolge: 1: Ich habe mich ausdrücklich davor bewahrt, shell = True zu setzen, damit ist es nicht. 2: vmrun_cmd ist eine globale Konstante, die jedes Mal genau so verwendet wird. 3: Nein. Die ausführbare Datei wurde bis zum Auftreten des Fehlers nicht aufgerufen - das ist der Anfang der Zeichenfolge, die den Pfad angibt. –

+0

@Rob Carr: meine Antwort bearbeitet, bitte versuchen Sie den Code über – nosklo

-1

2 Dinge

1)

Sie wollen wahrscheinlich nicht Rohr verwenden, wenn der Ausgang des Unterprogrammes größer als 64 KB ist, ist es wahrscheinlich, dass Ihr Prozess zum Absturz bringen. http://thraxil.org/users/anders/posts/2008/03/13/Subprocess-Hanging-PIPE-is-your-enemy/

2) subprocess.Popen hat ein Keyword-Argument Shell, so dass es, als ob die Shell Ihre Argumente Parsen wurde, das Setzen von Shell = True sollte das tun, was Sie wollen.

1

Ich glaube, dass list2cmdline(), die die Verarbeitung Ihrer Liste args, spaltet jede Zeichenfolge arg auf Leerzeichen, es sei denn, die Zeichenfolge enthält doppelte Anführungszeichen. So würde ich erwarten,

vmrun_cmd = r'"c:/Program Files/VMware/VMware Server/vmware-cmd.bat"' 

zu sein, was Sie wollen.

Wahrscheinlich möchten Sie auch die anderen Argumente (wie target_vm) in doppelte Anführungszeichen setzen, vorausgesetzt, dass sie ebenfalls jeweils ein eindeutiges Argument darstellen, das der Befehlszeile angezeigt wird. Etwas wie

r'"%s"' % target_vm 

(zum Beispiel) sollte passen. Siehe

the list2cmdline documentation

D'A

+0

Nun, target_vm ist ein Argument, anstatt eine Konstante, also, was ist die beste Methode für doppelte Anführungszeichen in dieser Situation? –

+0

Ich würde es wahrscheinlich als r '"% s"'% target_vm – darch

+0

Mann, das ist schwer zu lesen in den Kommentar. Verschieben Sie es zur Antwort. – darch

-2

Möglicherweise dummen Vorschlag, aber vielleicht die folgenden versuchen, zu entfernen subprocess + Leerzeichen aus der Gleichung:

import os 
from subprocess Popen, PIPE 

os.chdir(
    os.path.join("C:", "Program Files", "VMware", "VMware Server") 
) 

p = Popen(
    ["vmware-cmd.bat", target_vm, list_arg, list_arg2], 
    stdout=PIPE 
).communicate()[0] 

Es ist auch einen Versuch wert sein könnte. .

2

In Python auf MS Windows, der Subp Die rocess.Popen-Klasse verwendet die CreateProcess-API, um den Prozess zu starten. CreateProcess verwendet eine Zeichenfolge und nicht etwa ein Array von Argumenten. Python verwendet subprocess.list2cmdline, um die Liste der Argumente in eine Zeichenfolge für CreateProcess zu konvertieren.

Wenn ich du wäre, würde ich sehen, was subprocess.list2cmdline (args) zurückgibt (wo args das erste Argument von Popen ist). Es wäre interessant zu sehen, ob es das erste Argument zitiert.

Natürlich gilt diese Erklärung möglicherweise nicht in einer Cygwin-Umgebung.

Nachdem ich das alles gesagt habe, habe ich kein MS Windows.

-1

Hier ist, was ich nicht mag

vmrun_cmd = r"c:/Program Files/VMware/VMware Server/vmware-cmd.bat" 

Sie haben Leerzeichen im Namen des Befehls selbst - die Shell ist rätselhaft. Daher wird das '' c: \ Programm 'nicht als interner oder externer Befehl, ausführbares Programm oder Batchdatei erkannt. "

Option 1 - legen Sie Ihre .BAT-Datei woanders ab. In der Tat, setzen Sie Ihre gesamte VMWare woanders hin. Hier ist die Regel: Verwenden Sie nicht "Programme" Verzeichnis für alles. Es ist einfach falsch.

Option 2 - zitiere den vmrun_cmd Wert

vmrun_cmd = r'"c:/Program Files/VMware/VMware Server/vmware-cmd.bat"' 
4

Wenn Sie Leerzeichen im Pfad haben, habe der einfachste Weg, ich fand sie diese richtig bekommen interpretiert.

subprocess.call('""' + path + '""') 

Ich weiß nicht, warum genau doppelte Anführungszeichen benötigt, aber das ist, was funktioniert.

0

Ein Problem ist, dass, wenn der Befehl mit Anführungszeichen umgeben ist und keine Leerzeichen hat, dies auch die Shell verwirren könnte.

So mache ich das:

if ' ' in raw_cmd: 
    fmt = '"%s"' 
else: 
    fmt = '%s' 

cmd = fmt % raw_cmd 
0

Das ziemlich schwieriges Problem für die letzten drei uns .... nichts gesagt bisher funktioniert hat, weder mit r „“ oder Popen mit einer Liste war und so auf. Was am Ende funktionierte, war eine Kombination aus Formatzeichenfolge und r "". Also meine Lösung ist dies:

subprocess.Popen("{0} -f {1}".format(pathToExe, r'"%s"' % pathToVideoFileOrDir)) 

wo beide Variablen pathToExe und pathToVideoFileOrDir Leerzeichen in ihrem Weg haben. Die Verwendung von \ "innerhalb der formatierten Zeichenfolge funktionierte nicht und führte zum selben Fehler, dass der erste Pfad nicht mehr korrekt erkannt wurde.