2009-04-30 6 views
16

मैं एक रैपर स्क्रिप्ट पर काम कर रहा हूं जो वर्चुअल मशीन स्टार्टअप/शटडाउन/रजिस्टर/पंजीकरण/कार्यवाही के स्वचालन के लिए अनुमति देने वाला एक वीएमवेयर निष्पादन योग्य व्यायाम करेगा। मैं निष्पादन योग्य आवेदक को संभालने के लिए उपप्रोसेस का उपयोग करने की कोशिश कर रहा हूं, लेकिन एक्जिक्यूटिव पथ में और निष्पादन योग्य के पैरामीटर में रिक्त स्थान को उपप्रोसेसर द्वारा सही तरीके से संभाला नहीं जा रहा है। नीचे एक कोड टुकड़ा है:एकाधिक तर्कों में रिक्त स्थान होने पर उपप्रोसेस का उपयोग कैसे करें?

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 

अगर मैं vm_list2 फ़ंक्शन को कॉल करें, मैं निम्नलिखित उत्पादन प्राप्त करें:

$ ./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 

अगर मैं vm_start समारोह है, जो एक पथ-टू-VM पैरामीटर की आवश्यकता है कहते हैं, मैं निम्नलिखित उत्पादन प्राप्त करें:

$ ./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. 

जाहिर है, एम्बेडेड रिक्त स्थान के साथ एक दूसरे पैरामीटर की उपस्थिति तरीका है कि उपप्रक्रिया पहले पैरामीटर व्याख्या करने के तरीके में फेरबदल किया गया है। इसे हल करने के तरीके पर कोई सुझाव?

python2.5.2/cygwin/WinXP

+0

सी में आपकी स्लैश क्यों हैं:/प्रोग्राम फ़ाइलें/वीएमवेयर/वीएमवेयर सर्वर/vmware-cmd। बल्ले गलत तरीके से जा रहा है? क्या यह सी नहीं है: \ प्रोग्राम फ़ाइलें \ ...? –

+2

ठीक है, साइगविन * निक्स पोर्ट है, इसलिए यह मानक (या जो मानक मैं समझता हूं) की तरह लगता है * निक्स स्लैश नोटेशन मेरी समझ यह है कि उपप्रोसेसर को अलग-अलग सिस्टम की जरूरतों के लिए विभाजक का अनुवाद करना चाहिए। –

+0

क्या यह अभी हल हो गया है? – Gohan

उत्तर

-2

आप आर क्यों प्रयोग कर रहे हैं ""? मेरा मानना ​​है कि यदि आप शुरुआत से "आर" को हटाते हैं, तो इसे मानक स्ट्रिंग के रूप में माना जाएगा जिसमें रिक्त स्थान हो सकते हैं। खोल को भेजते समय पाइथन को स्ट्रिंग को ठीक से उद्धृत करना चाहिए।

+0

मैंने इसे चेक किया है, और कच्ची स्ट्रिंग स्थिति व्यवहार को बदलती नहीं है। –

+2

आर का उपयोग करने के लिए समझ में आता है " ... \ ... "विंडोज फ़ाइल नामों के लिए। –

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

इस संदेश को प्राप्त करने के लिए, आप या तो कर रहे हैं:

  1. shell=True का उपयोग करना:

    vmrun_cmd = r"c:\Program Files\VMware\VMware Server\vmware-cmd.bat" 
    subprocess.Popen(vmrun_cmd, shell=True) 
    
  2. अपने कोड

  3. से इस त्रुटि हो रही के अन्य भाग पर vmrun_cmd बदलने vmware-cmd.bat
  4. के अंदर कुछ

इन्हें आज़माएं:

  • खुला एक अजगर शीघ्र, निम्नलिखित कमांड चलाएँ:

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

अगर वह काम करता है, तो के हवाले से मुद्दों सवाल से बाहर हैं। यदि नहीं, तो आपने समस्या को अलग कर दिया है।

+0

क्रम में: 1: मैं स्पष्ट रूप से खोल = सही सेट करने से दूर रहा, ताकि है न। 2: vmrun_cmd एक वैश्विक स्थिरता है जो हर बार ठीक उसी तरह प्रयोग की जाती है। 3: नहीं। निष्पादन योग्य उस समय तक नहीं बुलाया गया है जब त्रुटि होती है - यह स्ट्रिंग की शुरुआत है जो इसे पथ निर्दिष्ट करती है। –

+0

@Rob Carr: मेरा उत्तर संपादित करें, कृपया – nosklo

-1

2 बातें

1)

आप शायद पाइप उपयोग करने के लिए नहीं करना चाहते हैं Subprogram के उत्पादन 64KB से अधिक है यह है की संभावना अपनी प्रक्रिया दुर्घटना होगा। http://thraxil.org/users/anders/posts/2008/03/13/Subprocess-Hanging-PIPE-is-your-enemy/

2) Subprocess.Popen, कोई कीवर्ड तर्क खोल है यह बनाने के रूप में करता है, तो खोल अपने तर्क को पार्स किया गया है, खोल की स्थापना = सच आप क्या चाहते हैं क्या करना चाहिए।

1

मेरा मानना ​​है कि list2cmdline(), जो आपकी सूची प्रसंस्करण कर रहा है, whitespace पर किसी भी स्ट्रिंग तर्क को विभाजित करता है जब तक कि स्ट्रिंग में दोहरे उद्धरण शामिल हैं। तो मैं

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

जो आप चाहते हैं उसके लिए उम्मीद करेंगे।

आप अन्य तर्कों (जैसे target_vm) को इस धारणा पर डबल कोट्स में घूमना चाहते हैं कि वे भी कमांड लाइन में मौजूद एक अलग तर्क का प्रतिनिधित्व करते हैं।

r'"%s"' % target_vm 

(उदाहरण के लिए) के अनुरूप कुछ होना चाहिए।

the list2cmdline documentation

डी 'एक

+0

से ऊपर दिए गए कोड को आज़माएं, ठीक है, target_vm निरंतर की बजाय एक बहस है, तो उस स्थिति में डबल उद्धरण के लिए सबसे अच्छी विधि क्या है? –

+0

मैं शायद इसे r '"% s"'% target_vm – darch

+0

मैन के रूप में वाक्यांश दूंगा, जो टिप्पणी में पढ़ना मुश्किल है। इसे उत्तर में ले जाना। – darch

-2

शायद बेवकूफ सुझाव देखें, लेकिन शायद समीकरण से उपप्रक्रिया + रिक्त स्थान को हटाने के लिए, निम्न प्रयास करें:

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] 

यह भी कोशिश कर रहा लायक हो सकता है।

p = Popen(
    [os.path.join("C:", "Program Files", "VMware", "VMware Server", "vmware-cmd.bat"), ... 
2

एमएस विंडोज़ पर पायथन में, उप rocess.Popen क्लास प्रक्रिया शुरू करने के लिए CreateProcess API का उपयोग करता है। CreateProcess तर्कों की एक सरणी की तरह कुछ स्ट्रिंग लेता है। Python CreateProcess के लिए स्ट्रिंग में तर्कों की सूची को रूपांतरित करने के लिए subprocess.list2cmdline का उपयोग करता है।

यदि मैं आप थे, तो मैं देखता हूं कि subprocess.list2cmdline (args) रिटर्न (जहां तर्क Popen का पहला तर्क है)। यह देखना दिलचस्प होगा कि यह पहले तर्क के आसपास उद्धरण डाल रहा है या नहीं।

बेशक, यह स्पष्टीकरण सिगविन पर्यावरण में लागू नहीं हो सकता है।

यह सब कहकर, मेरे पास एमएस विंडोज नहीं है। जो अपने खोल चौंकाने वाला है -

-1

यहाँ मैं आदेश खुद के नाम पर रिक्त स्थान

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

आप मिल गया है पसंद नहीं है क्या। इसलिए "सी: \ प्रोग्राम 'को आंतरिक या बाहरी कमांड, ऑपरेट करने योग्य प्रोग्राम या बैच फ़ाइल के रूप में पहचाना नहीं गया है।"

विकल्प 1 - अपना बीएटी फ़ाइल कहीं और रखें। दरअसल, अपने सभी वीएमवेयर कहीं और रखें। यहां नियम है: किसी भी चीज़ के लिए "प्रोग्राम फ़ाइलें" निर्देशिका का उपयोग न करें। यह सिर्फ गलत है।

विकल्प 2 - vmrun_cmd मान को उद्धृत

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

आप रास्ते में रिक्त स्थान है, तो सबसे आसान तरीका मैं उन्हें व्याख्या ठीक से इस है पाने के लिए मिल गया है।

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

मुझे नहीं पता कि इसे डबल डबल कोट्स की आवश्यकता क्यों है, लेकिन यह वही काम करता है।

0

एक समस्या यह है कि यदि आदेश उद्धरणों से घिरा हुआ है और इसमें रिक्त स्थान नहीं हैं, तो यह शेल को भी भ्रमित कर सकता है।

तो मैं इस कार्य करें:

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

cmd = fmt % raw_cmd 
0

कि पिछले तीन हमारे लिए काफी कठिन समस्या थी .... कुछ भी नहीं कहा गया है अब तक किया काम, न तो आर का उपयोग कर "" या popen एक सूची के साथ और इतने पर। अंत में काम क्या था प्रारूप स्ट्रिंग और आर "" का संयोजन था। तो मेरी समाधान यह है:

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

जहां दोनों चर pathToExe और pathToVideoFileOrDir उनके रास्ते में व्हाइटस्पेस है। \ "स्वरूपित स्ट्रिंग के भीतर \ n का उपयोग नहीं किया गया और परिणामस्वरूप एक ही त्रुटि में पाया गया कि पहला पथ अब सही ढंग से नहीं पता चला है।

संबंधित मुद्दे