পাইথন সাবপ্রসেসক্লায়েল () প্রত্যাশার মতো কাজ করছে না


11

আমি কীভাবে পাইথনে একটি সেটআপ স্ক্রিপ্ট তৈরি করতে পারি সে সম্পর্কে নিজেকে জানার উপায় হিসাবে আমি এই খরগোশের গর্তটি শুরু করেছি। পাইথনের পছন্দটি এর সাথে আমার পরিচিতির মূল কারণ ছিল যদিও আমি নিশ্চিত যে এই কাজের জন্য পাইথনের চেয়ে আরও ভাল বিকল্প থাকবে।

এই স্ক্রিপ্টের লক্ষ্য হ'ল স্ক্রিপ্টটি চালিত মেশিনে আরওএস ইনস্টল করা এবং ক্যাটকিন পরিবেশ সেটআপ করা। দিকনির্দেশগুলি যথাক্রমে এখানে এবং এখানে পাওয়া যাবে

বর্তমানে যে স্ক্রিপ্টটি বসে আছে তা নিম্নরূপ:

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
ধন্যবাদ! আমি এই ছাপের মধ্যে ছিলাম যে সাবপ্রসেসক্ল্যাক্স সমস্ত শেল ব্যবহার করেছে, এবং অজানা ছিল যে এটি স্পষ্টভাবে বলতে হবে। উপরের কমান্ডটি ঠিক যেমনটি কাজ করেছিল ঠিক তেমন কাজ করেছে
beedy

1
কেন ব্যবহার os.chdir()করবেন না ?
জ্যাকব Vlijm

3
কীভাবে subprocess.call(['catkin_make'], cwd=os.path.expanduser('~/catkin_ws/src'))?
ম্যাট নর্ডহফ

shell=Trueডিফল্ট শেল কল করবে, যা ড্যাশ। যদি কোনও স্ক্রিপ্ট যা ওপিতে বাশিজম রয়েছে এটি ভেঙে যেতে পারে। আমি আমার উত্তরে সম্পাদনা যুক্ত করেছি, বিকল্প সমাধান হ'ল স্পষ্টভাবে নির্দিষ্ট শেলটি কল করা। বিশেষত দরকারী যদি কেউ সিএসপি স্ক্রিপ্ট নিয়ে কাজ করে থাকেন
সের্গেই কোলডিয়াজনি

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কিছুই অর্জন করে না: সিডাব্লুডি একটি প্রক্রিয়া নির্দিষ্ট পরিবর্তনশীল যা প্রক্রিয়াটি শেষ হয়ে গেলেই উপস্থিতি বন্ধ হয়ে যায়।
n23325681

@ প্রোগো ভালো কথা, আমি ওপি'র কমান্ড সম্পাদনা করার জন্য এতটাই মনোযোগী ছিলাম যে আমি cdএখানে খেয়ালও করি না যে এখানে কিছু করবে না। । । । তবে "বৈধ" হিসাবে, এটি এখনও যথাযথ বাক্য বলে আমি বিশ্বাস করি - যদি আমি এমন subprocess.call()কিছু দিই যা এটির মতো পাওয়া যায় না তবে এটি ['ls -l'] বৈধ হবে না
সের্গি কলডিয়াজহনি

@progo, দয়া করে এখানে ক্লিক করুন একটি ছোট সম্পাদনা
Sergiy Kolodyazhnyy

3

os.chdir()পরিবর্তে ব্যবহার করুন।

বিদ্যমান উত্তরে উল্লিখিত সমস্যাগুলি বাদে, আমি ডিরেক্টরিটি পরিবর্তন করতে shell=Trueবা ব্যবহার করতে পছন্দ করব না subprocess.call()

পাইথনের ডিরেক্টরি পরিবর্তন করার নিজস্ব পদ্ধতি রয়েছে os.chdir()(ভুলে যাবেন না import os)। ~("হোম") বিভিন্ন উপায়ে সংজ্ঞায়িত করা যায়, এও os.environ["HOME"]

shell=Trueওভারটিও এখানে পড়তে পারা যায় বলে কারণগুলি


0

নোট করুন যে ব্যবহারের os.chdir()ফলে অনিচ্ছাকৃত পার্শ্ব-প্রতিক্রিয়া হতে পারে, উদাহরণস্বরূপ যদি আপনি মাল্টিথ্রেডিং ব্যবহার করছেনsubprocessপদ্ধতিগুলি সমস্ত cwdকীওয়ার্ড আর্গুমেন্ট সরবরাহ করে যা আপনার অজগর প্রক্রিয়ার অন্যান্য অংশগুলিকে প্রভাবিত না করে সেই ডিরেক্টরিতে অনুরোধ করা সাবপ্রসেসটি চালাবে।

আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.