अजगर subprocess.call () उम्मीद के मुताबिक काम नहीं कर रहा है


11

मैंने इस खरगोश के छेद को अपने आप से परिचित करने के लिए एक साधन के रूप में शुरू किया कि कैसे अजगर में एक सेटअप स्क्रिप्ट बनाने के बारे में जाना जाएगा। अजगर की पसंद बस इसके साथ मेरी परिचितता में निहित थी, जबकि मुझे यकीन है कि इस कार्य के लिए अजगर की तुलना में बेहतर विकल्प होंगे।

इस स्क्रिप्ट का लक्ष्य ROS को स्क्रिप्ट चलाने वाली मशीन पर स्थापित करना था और कैटकिन वातावरण को भी सेटअप करना था। दिशाएं क्रमशः और यहां , यहां और यहां पाई जा सकती हैं।

वर्तमान में जो स्क्रिप्ट बैठता है वह इस प्रकार है:

subprocess.call(["sudo", "sh", "-c", "'echo \"deb http://packages.ros.org/ros/ubuntu $(lsb_release -sc) main\" > /etc/apt/sources.list.d/ros-latest.list'"])
subprocess.call(["sudo", "apt-key", "adv", "--keyserver", "hkp://ha.pool.sks-keyserver.net:80", "--recv-key", "0xB01FA116"])
subprocess.call(["sudo", "apt-get", "update"])
subprocess.call(["sudo", "apt-get", "install", "ros-kinetic-desktop-full", "-y"])
subprocess.call(["sudo", "rosdep", "init"])
subprocess.call(["rosdep", "update"])
subprocess.call(["echo", '"source /opt/ros/kinetic/setup.bash"', ">>", "~/.bashrc", "source", "~/.bashrc"])
subprocess.call(["sudo", "apt-get", "install", "python-rosinstall", "-y"])
mkdir_p(os.path.expanduser('~') + "/catkin_ws/src")
subprocess.call(["(cd "+ os.path.expanduser('~') + "/catkin_ws/src)"])
subprocess.call(["(cd "+ os.path.expanduser('~') + "/catkin_ws && catkin_make)"])
subprocess.call(["(cd "+ os.path.expanduser('~') + "/catkin_ws && source devel/setup.bash"])

जब स्क्रिप्ट वर्तमान में चलती है, तो यह त्रुटि के साथ समाप्त हो जाती है:

Traceback (most recent call last):
  File "setup.py", line 46, in <module>
    subprocess.call(["(cd "+ os.path.expanduser('~') + "/catkin_ws/src)"])
  File "/usr/lib/python2.7/subprocess.py", line 523, in call
    return Popen(*popenargs, **kwargs).wait()
  File "/usr/lib/python2.7/subprocess.py", line 711, in __init__
    errread, errwrite)
  File "/usr/lib/python2.7/subprocess.py", line 1343, in _execute_child
    raise child_exception
OSError: [Errno 2] No such file or directory

मैंने सत्यापित किया है कि टर्मिनल विंडो से मैन्युअल रूप से निष्पादित होने पर कमांड सही ढंग से काम करता है, और जैसा कि मेरा मानना ​​है कि यह एक मूल गलतफहमी है कि यह स्क्रिप्ट और इसका दायरा ओएस के भीतर कैसे संभाला जाता है। जो हिस्सा मुझे बहुत भ्रम में डाल रहा है, वह यह है कि यह शिकायत करता है कि यह प्रदान की गई निर्देशिका का पता लगाने में असमर्थ है, जबकि मैंने सत्यापित किया है कि यह निर्देशिका मौजूद है। जब कमांड को अजगर से मुद्रित किया जाता है और टर्मिनल विंडो में चिपकाया जाता है, तो कोई त्रुटि नहीं आती है।


पायथन का अपना हैos.chdir()
जैकब वलिजम

1
यदि आप पायथन 3 का उपयोग कर रहे हैं, तो बस cwdतर्क पास करेंcall
intsco

जवाबों:


18

डिफ़ॉल्ट रूप subprocess.callसे हमारे आदेशों को चलाने के लिए एक शेल का उपयोग नहीं किया जाता है ताकि आप कमांड को खोल न सकें cd

अपने कमांड चलाने के लिए एक शेल का उपयोग करने के लिए shell=Trueपैरामीटर के रूप में उपयोग करें । उस मामले में यह एक सूची के बजाय एक ही स्ट्रिंग के रूप में अपने आदेश पारित करने के लिए सिफारिश की है। और जैसा कि यह एक शेल द्वारा चलाया जाता है, जिसका उपयोग ~/आप अपने रास्ते में भी कर सकते हैं :

subprocess.call("(cd ~/catkin_ws/src && catkin_make)", shell=True)

1
धन्यवाद! मैं इस धारणा के तहत था कि सबप्रोसेस.कॉल ने एक शेल का उपयोग किया था, और इस बात से अनजान था कि इसे स्पष्ट रूप से कहा जाना था। उपरोक्त आदेश ने ठीक उसी तरह से काम किया जैसा कि
बीडी

1
उपयोग क्यों नहीं os.chdir()?
जैकब वलिज्म

3
कैसे के बारे में subprocess.call(['catkin_make'], cwd=os.path.expanduser('~/catkin_ws/src'))?
मैट नॉर्डहॉफ

shell=Trueडिफ़ॉल्ट शेल को कॉल करेगा, जो डैश है। यदि कोई स्क्रिप्ट जिसमें ओपी में बैशमिज़ हैं तो वह टूट सकता है। मैंने अपने उत्तर में संपादन जोड़ लिया है, वैकल्पिक समाधान स्पष्ट रूप से विशिष्ट शेल को कॉल करना होगा। विशेष रूप से उपयोगी है अगर कोई csh स्क्रिप्ट के साथ काम कर रहा है
Sergiy Kolodyazhnyy

1
सबसे अच्छा समाधान मैट नॉर्डहॉफ सुझाव है। निश्चित आदेशों के साथ shell=True भी उपयोग करने से सुरक्षा कमजोरियां खुलती हैं (जैसे शेलशॉक को एक कमजोर सिस्टम पर चालू किया जा सकता है)। अंगूठे का नियम: यदि आप का उपयोग कर से बचने कर सकते shell=Trueआप चाहिए यह से बचें। cwdपैरामीटर वहाँ वास्तव में कॉल की तरह ओ पी चाहता है क्या करना है।
बकुरीउल

5

subprocess.call() पहली सूची में स्पष्ट रूप से एक वैध शेल कमांड होने के साथ, एक सूची की उम्मीद है। उदाहरण के लिए इसकी तुलना करें:

>>> subprocess.call(['echo hello'])
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/usr/lib/python2.7/subprocess.py", line 523, in call
    return Popen(*popenargs, **kwargs).wait()
  File "/usr/lib/python2.7/subprocess.py", line 711, in __init__
    errread, errwrite)
  File "/usr/lib/python2.7/subprocess.py", line 1343, in _execute_child
    raise child_exception
OSError: [Errno 2] No such file or directory
>>> subprocess.call(['echo', 'hello'])
hello
0

आपके मामले में, subprocess.call(["(cd "+ os.path.expanduser('~') + "/catkin_ws/src)"])द्विआधारी को खोजने की उम्मीद करेंगे जो ऐसा दिखता है (नोट स्पेसकल्चर को पीछे छोड़ना)

 cd\ /home/user/catkin_ws/src

यह एक एकल नाम के रूप में माना जाता है जो आपके सिस्टम पर कहीं रहने की उम्मीद है। आप वास्तव में क्या करना चाहते हैं:

 subprocess.call(["cd", os.path.expanduser('~') + "/catkin_ws/src"])

ध्यान दें कि मैंने अल्पविराम के चारों ओर कोष्ठक को हटा दिया है, क्योंकि उप-संस्करण का उपयोग करने का कोई कारण नहीं है।

संपादित करें :

लेकिन यह पहले से ही टिप्पणी में प्रोगो द्वारा उल्लेख किया गया है कि cdइस मामले में उपयोग करना बेमानी है। फ्लोरियन के उत्तर में भी ठीक से उल्लेख subprocess.call()नहीं है कि शेल का उपयोग नहीं किया गया है। आप दो तरीकों से संपर्क कर सकते हैं। एक, आप उपयोग कर सकते हैंsubprocess.call("command string",shell=True)

दूसरा तरीका, विशिष्ट शेल को स्पष्ट रूप से कॉल करना है। यह विशेष रूप से उपयोगी है यदि आप एक स्क्रिप्ट चलाना चाहते हैं जिसमें विशिष्ट शेल की आवश्यकता होती है। इस प्रकार आप कर सकते हैं:

subprocess.call(['bash' , os.path.expanduser('~')  + "/catkin_ws/src"  ) ] )

1
call()एक वैध शेल कमांड की उम्मीद नहीं है; यह एक वास्तविक निष्पादन योग्य मार्ग खोजने की अपेक्षा करता है। और एक स्टैंडअलोन cdको कॉल करने से कुछ भी हासिल नहीं होता है: CWD एक प्रक्रिया विशिष्ट चर है जो प्रक्रिया से बाहर निकलते ही मौजूद रहना बंद कर देता है।
nperson325681

@ अच्छी बात है, मैं ओपी के आदेश को संपादित करने पर इतना ध्यान केंद्रित कर रहा था कि मुझे यह भी ध्यान नहीं था कि यहां cdकुछ भी नहीं होगा। । । । लेकिन "वैध" के रूप में, यह अभी भी उपयुक्त है कि मेरा मानना ​​है - अगर मैं subprocess.call()कुछ देता हूं तो वह नहीं मिल सकता है, जैसे ['ls -l'] , यह वैध नहीं होगा
Sergiy Kolodyazhnyy

@progo ने एक छोटा सा संपादन किया, कृपया समीक्षा करें
Sergiy Kolodyazhnyy

3

os.chdir()इसके बजाय उपयोग करें ।

मौजूदा उत्तरों में वर्णित मुद्दों के अलावा, मैं न तो उपयोग करना पसंद करूंगा shell=Trueऔर न ही subprocess.call()निर्देशिका बदलने के लिए।

पायथन में निर्देशिका बदलने का अपना तरीका है os.chdir()(मत भूलना import os)। ~("घर") को कई तरीकों से परिभाषित किया जा सकता है, एओ os.environ["HOME"]

यह पसंद करने के कारण कि यहाँ परshell=True ao पढ़ा जा सकता है


0

ध्यान दें कि os.chdir()यदि आप मल्टीथ्रेडिंग का उपयोग कर रहे हैं तो अनपेक्षित साइड-इफेक्ट्स का उपयोग कर सकते हैंsubprocessसभी तरीके एक cwdखोजशब्द तर्क प्रदान करते हैं जो उस निर्देशिका में अनुरोध किए गए उपप्रकार को चलाएगा, बिना आपकी अजगर प्रक्रिया के अन्य भागों को प्रभावित किए बिना।

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.