subprocess মডিউল

subprocess মডিউল

অনেক সময় পাইথন প্রোগ্রাম থেকেই নতুন একটি প্রোগ্রাম বা প্রসেস চালু করার দরকার পড়ে অথবা একটা শেল কমান্ড চালিয়ে তার আউটপুট জানার দরকার পড়ে। সাবপ্রসেস (subprocess) মডিউলের সহযোগিতায় এসব কাজ আমরা একেবারে নির্বিঘ্নে করতে পারি। আরেকটু বিস্তারিতভাবে বলতে গেলে, সাবপ্রসেস মডিউলের সহায়তায় আমরা একটা প্রসেস শুরু করতে পারি, এর ইনপুট/আউটপুট/এরর পাইপের সাথে সংযোগ স্থাপন করতে পারি আর এর রিটার্ন কোডগুলো সহজেই দেখতে পারি। অপারেটিং সিস্টেম মডিউল চ্যাপ্টারে অবশ্য আমরা প্রোগ্রাম বা প্রসেস চালু করার একটা তরিকা শিখেছি কিন্তু সেটা একেবারে বাচ্চা পদ্ধতি। শুধুই কমান্ড চালানো যায় কিন্তু কমান্ড চালিয়ে কী আউটপুট পেলাম তা ক্যাপচার করা যায় না, একটি কমান্ড চালিয়ে পরবর্তী সময়ে ওই কমান্ডের সাথে যোগাযোগ করে ইনপুট পাস করা যায় না, এমনটি এররও ক্যাচ করা যায় না। সাবপ্রসেস মডিউল হলো এসব সমস্যার শাহি সমাধান।

run()

রান ফাংশন আলোচনার আগে একটা তথ্য জানানোর দরকার আছে। এই ফাংশনটা পাইথন ৩.৫-এ প্রথম ইন্ট্রোডিউস করা হয়। সুতরাং এর আগের ভার্সন যদি কেউ ব্যবহার করে থাকি, তাহলে এই ফাংশনের কাজকর্ম করতে পারব না। যাহোক, পাইথন থেকে একটা প্রসেস বা শেল কমান্ড চালু করার সবচেয়ে সহজ উপায় হলো রান ফাংশনের সহায়তা নেওয়া। যেমন—

>>> import subprocess
>>> output = subprocess.run(["ls", "-l"])
total 72
drwxr-xr-x  2 maateen maateen  4096 Dec 2415:48 Desktop
drwxr-xr-x   6 maateen maateen  4096 Dec 1223:42 Documents
drwxr-xr-x  18 maateen maateen 12288 Dec 2413:54 Downloads
drwxrwxr-x  5 maateen maateen   4096 Dec  412:37 MEGAsync
drwxr-xr-x   2 maateen maateen   4096 Jul 2123:19 Music
drwxr-xr-x  10 maateen maateen 20480 Dec 2316:54 Pictures
drwxr-xr-x   3 maateen maateen   4096 Jun 222016 Public
drwxr-xr-x   2 maateen maateen   4096 Apr 262016 Templates
drwxr-xr-x   5 maateen maateen   4096 Dec 2401:26 Videos
drwxrwxr-x 16 maateen maateen   4096 Dec 1420:18 workspace
>>> print(output)
CompletedProcess(args=['ls', '-l'], returncode=0)

কী সুন্দর আউটপুট পেয়ে গেলাম! কিন্তু এত কিছুর মাঝেও একটি ঝামেলা আছে। output ভেরিয়েবলে কিন্তু আমরা আউটপুট ক্যাপচার করতে পারিনি। আসলে এভাবে হ্যাঁচকামারা কায়দায় শেল কমান্ড রান করলে কোনো আউটপুটই ক্যাপচার করা যাবে না। তাহলে কী উপায়? কী উপায়?

>>> import subprocess
>>> output = subprocess.run(['ls', '-l'], stdout=subprocess.PIPE)
>>> type(output)
<class 'subprocess.CompletedProcess'>
>>> print(output)
CompletedProcess(args=['ls', '-l'], returncode=0, stdout=b'total 30352\n-rw-rw-r-- 1 maateen maateen    93074 Nov 17 14:13 20161116092156306283.pdf\n-rw-rw-r-- 1 maateen maateen      131 Nov 20 12:21 hijibiji.py\n-rwxrwxrwx 1 maateen maateen 30966208 Oct 25 19:35 python_101.pdf\n-rw-rw-r-- 1 maateen maateen       95 Dec 24 21:37 test.py\n')
>>> type(output.stdout)
<class 'bytes'>
>>> result = output.stdout.decode('UTF-8')
>>> print(result)
total 30352
-rw-rw-r--1 maateen maateen    93074 Nov 1714:1320161116092156306283.pdf
-rw-rw-r--1 maateen maateen      131 Nov 2012:21 hijibiji.py
-rwxrwxrwx 1 maateen maateen 30966208 Oct 2519:35 python_101.pdf
-rw-rw-r--1 maateen maateen       95 Dec 2421:37 test.py

এটা কিন্তু একটা উপায় বটে! রান ফাংশনে আমরা নতুন একটা প্যারামিটার stdout=subprocess.PIPE পাস করেছি। তারপর যে আউটপুটটা পেলাম সেটা আউটপুট ভেরিয়েবলে ক্যাপচার করে আউটপুটের টাইপ চেক করেছি। এখানে আছে সাবপ্রসেস মডিউলের CompletedProcess ক্লাসের একটি অবজেক্ট। তারপর এর মধ্যে কী আছে দেখার জন্য আমরা ভেরিয়েবলটাকে প্রিন্ট করেছি। এখানে অনেক কিছুই আছে কিন্তু আমাদের দরকার শুধু stdout-এর উপাদানগুলো। সে জন্য আমরা output.stdout-এর টাইপ চেক করে দেখলাম, এটি বাইট টাইপের। বাইট তো কী হয়েছে? আমরা তো চাইলেই এটিকে UTF-8-এ ডিকোড করতে পারি। এবং ডিকোড করার পর আমরা পেয়ে গেলাম আমাদের কাঙ্ক্ষিত রেজাল্ট।

একটা কথা বলে রাখা ভালো যে— subprocess.run(args, *, stdin=None, input=None, stdout=None, stderr=None, shell=False, timeout=None, check=False, encoding=None, errors=None) সবসময় CompletedProcess ক্লাসের একটা ইনস্ট্যান্স রিটার্ন করে। encoding আর errors প্যারামিটার দুটি পাইথন ৩.৬-এ ইন্ট্রোডিউস করা হয়েছে।

আর রান ফাংশনের মধ্যে আমরা প্রথম প্যারামিটার হিসেবে সব সময় প্রসেস লঞ্চ (শুরু) করার কমান্ড বা শেল কমান্ড দেব। কিন্তু এখানে চিন্তাভাবনার অবকাশ আছে। একটা উদাহরণ দিলে পরিষ্কার হয়ে যাবে:

>>> import subprocess
>>> output = subprocess.run('uname')
Linux
>>> output = subprocess.run('uname -r')
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/usr/lib/python3.6/subprocess.py", line 693, in run
    with Popen(*popenargs, **kwargs) as process:
  File "/usr/lib/python3.6/subprocess.py", line 947, in __init__
    restore_signals, start_new_session)
  File "/usr/lib/python3.6/subprocess.py", line 1551, in _execute_child
    raise child_exception_type(errno_num, err_msg)
FileNotFoundError: [Errno 2] No such file or directory: 'uname -r'
>>> output = subprocess.run(['uname', '-r'])
4.4.0-58-generic

আমরা যদি শুধু সিঙ্গেল ওয়ার্ডেড কমান্ডকে স্ট্রিং আর্গুমেন্ট হিসেবে পাস করি তাহলে কোনো ঝামেলা নেই। কিন্তু যদি এমন কোনো কমান্ড দিতে চাই যার মধ্যে স্পেস রয়েছে, সে ক্ষেত্রে লিস্ট আকারে আর্গুমেন্ট পাস করতে হবে। যেমনটা আমরা আগের প্রোগ্রামে শেষের দিকে করেছি। এটাকে বলে টোকেনাইজেশন। আর একটু পরেই আমরা এর সম্পর্কে আরেকটু জানব।

Popen ক্লাস

সত্যি কথা বলতে কি, Popen ক্লাসের মাধ্যমেই সাবপ্রসেস মডিউলে যাবতীয় প্রসেস লঞ্চ (শুরু) ও ম্যানেজ করা হয়। এটার সবচেয়ে বড় সুবিধা হলো, এটা খুবই ফ্লেক্সিবল। তাই ডেভেলপারদের কম জ্বালা সহ্য করতে হয়।

class subprocess.Popen(args, bufsize=-1, executable=None, stdin=None, stdout=None, stderr=None, preexec_fn=None, close_fds=True, shell=False, cwd=None, env=None, universal_newlines=False, startupinfo=None, creationflags=0, restore_signals=True, start_new_session=False, pass_fds=(), *, encoding=None, errors=None) এ অনেকগুলো প্যারামিটার রয়েছে। একটা উদাহরণ দেখা যাক :

import subprocess

output = subprocess.Popen('uname')
print(type(output))
print(output)

আউটপুট

<class 'subprocess.Popen'>
<subprocess.Popen object at 0x7f585724a748>
Linux

সবকিছু কিন্তু অনেকটা ওই আগের run() ফাংশনের মতোই। পার্থক্য শুধু একটাই যে আউটপুট ক্যাপচার করার জন্য এক্সট্রা কোনো কারুকাজ করা লাগেনি। আর আর্গুমেন্ট পাসিংয়ের ক্ষেত্রে run() ফাংশনের নিয়মাবলিই প্রযোজ্য। কিন্তু কমান্ড টোকেনাইজেশনের জন্য আমরা একটা নতুন পদ্ধতি শিখব। আর সে জন্য ব্যবহার করব shlex মডিউলের split() ফাংশনকে।

import shlex, subprocess

command = 'uname -r'
args = shlex.split(command)
print(args)
output = subprocess.Popen(args)
print(output)

আউটপুট

['uname', '-r']
<subprocess.Popen object at 0x7f09acd75780>
4.4.0-58-generic

কী চমৎকার! split() ফাংশনের মধ্যে আমরা আমাদের কমান্ডটা পাস করলাম আর সে আমাদের টোকেনাইজড কমান্ডটা রিটার্ন করল। খুব সহজেই কিন্তু আমাদের কাজটা এবার হয়ে গেল। এবার আরেকটা উদাহরণ দেখা যাক :

import shlex, subprocess

command = 'uname -r'
args = shlex.split(command)
print(args)
output = subprocess.Popen(args)
print(output)
code = output.wait()
print(code)

আউটপুট

['uname', '-r']
<subprocess.Popen object at 0x7fa3ce8a4780>
4.4.0-58-generic
0

আমরা এই প্রসেসের রিটার্ন কোড চেক করে দেখেছি। একটা প্রসেসের রিটার্নকোড 0 হওয়া মানে সাকসেস আর নন-জিরো হওয়া মানে এরর। রিটার্নকোডকে এক্সিট স্ট্যাটাসও বলা হয়। ইতিপূর্বে কিন্তু run() ব্যবহার করার সময়েও আমরা returncode প্যারামিটারটা দেখেছিলাম। আচ্ছা, ক্লাসের ওই জঞ্জাল থেকে কি আমরা returncode-কে উদ্ধার করতে পারব? কীভাবে করা যায়? ভাবতে হবে! কাজটি দেখা যাক:

>>> import subprocess
>>> output = subprocess.run(["ls", "-l"])
total 72
drwxr-xr-x   2 maateen maateen  4096 Dec 2510:59 Desktop
drwxr-xr-x   6 maateen maateen  4096 Dec 1223:42 Documents
drwxr-xr-x  18 maateen maateen 12288 Dec 2509:16 Downloads
drwxrwxr-x  5 maateen maateen   4096 Dec  412:37 MEGAsync
drwxr-xr-x   2 maateen maateen   4096 Jul 2123:19 Music
drwxr-xr-x  10 maateen maateen 20480 Dec 2510:18 Pictures
drwxr-xr-x   3 maateen maateen   4096 Jun 222016 Public
drwxr-xr-x   2 maateen maateen   4096 Apr 262016 Templates
drwxr-xr-x   5 maateen maateen   4096 Dec 2401:26 Videos
drwxrwxr-x 16 maateen maateen   4096 Dec 1420:18 workspace
>>> print(output)
CompletedProcess(args=['ls', '-l'], returncode=0)
>>> print(output.returncode)
0
>>> print(type(output.returncode))
<class 'int'>

এখন Popen.communicate(input=None, timeout=None) নিয়ে আলোচনা চালানো যাক। আমরা একটা প্রসেস চালানোর পর যদি ওই প্রসেসের সাথে ইন্টারঅ্যাক্ট করার দরকার হয় তখন এই ফাংশনটা ব্যবহার করা হয়। communicate() ফাংশন আউটপুট ও এররের টাপল রিটার্ন করে। অপশনাল প্যারামিটার ইনপুটের মাধ্যমে চাইল্ড প্রসেসের কাছে ডেটা পাঠানো যায়। তবে আমরা যদি প্রসেসের stdin-এ ডেটা পাঠাতে চাই সে ক্ষেত্রে Popen অবজেক্ট stdin=PIPE-সহ তৈরি করতে হবে। একই রেজাল্ট টাপলে কারিশমা করার জন্য stdout=PIPEstderr=PIPE ব্যবহার করতে হবে।

পাইথনের অফিশিয়াল ডক থেকে একটা উদাহরণ দেখা যাক:

proc = subprocess.Popen(...)
try:
    outs, errs = proc.communicate(timeout=15)
except TimeoutExpired:
    proc.kill()
    outs, errs = proc.communicate()

এখানে timeout=15 দিয়ে ১৫ সেকেন্ড পর টাইমআউট হবে বুঝিয়েছে। যদি কোনো কারণে ১৫ সেকেন্ডের মধ্যে প্রসেসটা টার্মিনেট না করে, সে ক্ষেত্রে TimeoutExpired এক্সেপশন রেইজ হবে। তবে এই এক্সেপশনটাকে হ্যান্ডেল করে আবার প্রসেসের সাথে কমিউনিকেট করা হলে কোনো আউটপুটই খোয়া যাবে না। কী শান্তি! তবে যে প্রসেস চালু করেছি তা বন্ধ করা অনিবার্য। সে জন্য আমরা kill() মেথডের সহায়তা নিতে পারি।

call()

সাবপ্রসেস মডিউলের তিনটি আদিম ফাংশন আছে : call(), check_call()check_output()। ভবিষ্যতে এরা থাকবে কি না, তা নিয়ে জাতি সন্দিহান। run() ফাংশন দিয়ে আমরা এদের মোটামুটিভাবে রিপ্লেস করতে পারলেও কিন্তু এদের দরকার আছে।

কল ফাংশনটা খুবই সিম্পল। এর মধ্যে কমান্ড আর্গুমেন্ট হিসেবে পাস করা হলে প্রথমে কমান্ডটা চালাবে, তারপর কমান্ড চলা শেষ হবার জন্য ওয়েট করবে, শেষে returncode রিটার্ন করবে। উদাহরণ দেখা যাক:

>>> import subprocess
>>> output = subprocess.call(['ls', '-l'])
total 72
drwxr-xr-x   2 maateen maateen  4096 Dec 2510:59 Desktop
drwxr-xr-x   6 maateen maateen  4096 Dec 1223:42 Documents
drwxr-xr-x  18 maateen maateen 12288 Dec 2509:16 Downloads
drwxrwxr-x  5 maateen maateen   4096 Dec  412:37 MEGAsync
drwxr-xr-x   2 maateen maateen   4096 Jul 2123:19 Music
drwxr-xr-x  10 maateen maateen  20480 Dec 2510:18 Pictures
drwxr-xr-x   3 maateen maateen   4096 Jun 222016 Public
drwxr-xr-x   2 maateen maateen   4096 Apr 262016 Templates
drwxr-xr-x   5 maateen maateen   4096 Dec 2401:26 Videos
drwxrwxr-x 16 maateen maateen   4096 Dec 1420:18 workspace
>>> print(output)
0

আউটপুটের মধ্যে শুধু রিটার্নকোড বাদে আর কিছু নেই। আমরা চাইলে run() ফাংশন ব্যবহার করে এই প্রোগ্রামটার একটি ইকুইভ্যালেন্ট (সমতুল্য) প্রোগ্রাম লিখতে পারি।

>>> import subprocess
>>> output = subprocess.run(['ls', '-l']).returncode
total 72
drwxr-xr-x   2 maateen maateen  4096 Dec 2510:59 Desktop
drwxr-xr-x   6 maateen maateen  4096 Dec 1223:42 Documents
drwxr-xr-x  18 maateen maateen 12288 Dec 2509:16 Downloads
drwxrwxr-x  5 maateen maateen   4096 Dec  412:37 MEGAsync
drwxr-xr-x   2 maateen maateen   4096 Jul 2123:19 Music
drwxr-xr-x  10 maateen maateen 20480 Dec 2510:18 Pictures
drwxr-xr-x   3 maateen maateen   4096 Jun 222016 Public
drwxr-xr-x   2 maateen maateen   4096 Apr 262016 Templates
drwxr-xr-x   5 maateen maateen   4096 Dec 2401:26 Videos
drwxrwxr-x 16 maateen maateen   4096 Dec 1420:18 workspace
>>> print(output)
0

আরেকটি উদাহরণ দেখা যাক:

>>> subprocess.call('ls -l')
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/usr/lib/python3.6/subprocess.py", line 557, in call
    with Popen(*popenargs, **kwargs) as p:
  File "/usr/lib/python3.6/subprocess.py", line 947, in __init__
    restore_signals, start_new_session)
  File "/usr/lib/python3.6/subprocess.py", line 1551, in _execute_child
    raise child_exception_type(errno_num, err_msg)
FileNotFoundError: [Errno 2] No such file or directory: 'ls -l'

এরর থ্রো করেছে। কারণটা আমরা আগেই জেনেছি। কমান্ড আর্গুমেন্ট টোকেনাইজড করা নয়।

>>> subprocess.call('ls -l', shell=True)
total 72
drwxr-xr-x   2 maateen maateen  4096 Dec 2510:59 Desktop
drwxr-xr-x   6 maateen maateen  4096 Dec 1223:42 Documents
drwxr-xr-x  18 maateen maateen 12288 Dec 2509:16 Downloads
drwxrwxr-x  5 maateen maateen   4096 Dec  412:37 MEGAsync
drwxr-xr-x   2 maateen maateen   4096 Jul 2123:19 Music
drwxr-xr-x  10 maateen maateen 20480 Dec 2510:18 Pictures
drwxr-xr-x   3 maateen maateen   4096 Jun 222016 Public
drwxr-xr-x   2 maateen maateen   4096 Apr 262016 Templates
drwxr-xr-x   5 maateen maateen  4096 Dec 2401:26 Videos
drwxrwxr-x 16 maateen maateen  4096 Dec 1420:18 workspace
0

এখানে কোনো এরর নেই, এবারও কিন্তু আমরা কমান্ড আর্গুমেন্ট টোকেনাইজড করে পাস করিনি। তাহলে? আসলে এটা shell=True প্যারামিটারের কারিশমা। এই প্যারামিটার True সেট করা হলে আর্গুমেন্ট হিসেবে আমরা যে কমান্ডই দেব না কেন তা শেল প্রোগ্রাম প্রসেস করবে। লিনাক্সের ক্ষেত্রে ওপরের প্রোগ্রাম হলো /bin/sh -c 'ls -l'-এর সমতুল্য। যেমন:

>>> subprocess.call(['ls', '-l'], shell=True)
Desktop    Downloads  Music Public     Videos
Documents  MEGAsync   Pictures  Templates  workspace
0

এখানে আউটপুট পরিবর্তিত হয়ে গেছে। এখানেও ঘটনা আছে। যখন আমরা shell=True সেট করে কমান্ড আর্গুমেন্টের লিস্ট পাস করি তখন শেলের কাছে এই লিস্ট কমান্ডলাইন আর্গুমেন্ট হিসেবে পাস হয়। এ ক্ষেত্রে ওপরের প্রোগ্রামের সমতুল্য শেল কমান্ড হলো /bin/sh -c ls -l/bin/sh সব সময় -c এর পরের আর্গুমেন্টটাকে এক্সিকিউট করে। তাই দিন শেষে শেল কমান্ডটা এ রকম হয়— /bin/sh -c ls

check_call()

এর মধ্যে কমান্ড আর্গুমেন্ট হিসেবে পাস করা হলে প্রথমে কমান্ডটা চালাবে, তারপর কমান্ড চলা শেষ হওয়ার জন্য ওয়েট করবে, শেষে returncode জিরো হলে জিরো রিটার্ন করবে। আর নন-জিরো হলে CalledProcessError এক্সেপশন রেইজ করবে। CalledProcessError অবজেক্টের returncode অ্যাট্রিবিউটে রিটার্ন কোড থাকবে।

>>> import subprocess
>>> output = subprocess.check_call(['ls', '-l'])
total 72
drwxr-xr-x  2 maateen maateen  4096 Dec 2510:59 Desktop
drwxr-xr-x  6 maateen maateen  4096 Dec 1223:42 Documents
drwxr-xr-x  18 maateen maateen 12288 Dec 2509:16 Downloads
drwxrwxr-x  5 maateen maateen   4096 Dec  412:37 MEGAsync
drwxr-xr-x   2 maateen maateen   4096 Jul 2123:19 Music
drwxr-xr-x  10 maateen maateen  20480 Dec 2510:18 Pictures
drwxr-xr-x   3 maateen maateen   4096 Jun 222016 Public
drwxr-xr-x   2 maateen maateen   4096 Apr 262016 Templates
drwxr-xr-x   5 maateen maateen   4096 Dec 2401:26 Videos
drwxrwxr-x 16 maateen maateen   4096 Dec 1420:18 workspace
>>> print(output)
0

এখানে রিটার্নকোড ছিল জিরো তাই জিরো রিটার্ন করেছে, অন্যথায় এক্সেপশন রেইজ করত। আমরা চাইলে run() ফাংশন ব্যবহার করে এই প্রোগ্রামটির একটা ইকুইভ্যালেন্ট (সমতুল্য) প্রোগ্রাম লিখতে পারি।

>>> import subprocess
>>> output = subprocess.run(['ls', '-l'], check=True)
total 72
drwxr-xr-x   3 maateen maateen  4096 Dec 2512:26 Desktop
drwxr-xr-x   6 maateen maateen  4096 Dec 1223:42 Documents
drwxr-xr-x  18 maateen maateen 12288 Dec 2512:36 Downloads
drwxrwxr-x  5 maateen maateen   4096 Dec  412:37 MEGAsync
drwxr-xr-x   2 maateen maateen   4096 Jul 2123:19 Music
drwxr-xr-x  10 maateen maateen  20480 Dec 2512:26 Pictures
drwxr-xr-x   3 maateen maateen   4096 Jun 222016 Public
drwxr-xr-x   2 maateen maateen   4096 Apr 262016 Templates
drwxr-xr-x   5 maateen maateen   4096 Dec 2401:26 Videos
drwxrwxr-x 16 maateen maateen   4096 Dec 1420:18 workspace
>>> print(output)
CompletedProcess(args=['ls', '-l'], returncode=0)

check_output()

এর মধ্যে কমান্ড আর্গুমেন্ট হিসেবে পাস করা হলে প্রথমে কমান্ডটা চালাবে, তারপর কমান্ড চলা শেষ হওয়ার জন্য ওয়েট করবে, শেষে রিটার্নকোড জিরো হলে আউটপুট রিটার্ন করবে। আর নন-জিরো হলে CalledProcessError এক্সেপশন রেইজ করবে। CalledProcessError অবজেক্টের returncode অ্যাট্রিবিউটে রিটার্ন কোড আর output অ্যাট্রিবিউটে আউটপুট থাকবে।

>>> import subprocess
>>> output = subprocess.run(['ls', '-l'], check=True)
total 72
drwxr-xr-x   3 maateen maateen  4096 Dec 2512:26 Desktop
drwxr-xr-x   6 maateen maateen  4096 Dec 1223:42 Documents
drwxr-xr-x  18 maateen maateen 12288 Dec 2512:36 Downloads
drwxrwxr-x  5 maateen maateen  4096 Dec  412:37 MEGAsync
drwxr-xr-x   2 maateen maateen  4096 Jul 2123:19 Music
drwxr-xr-x  10 maateen maateen 20480 Dec 2512:26 Pictures
drwxr-xr-x   3 maateen maateen  4096 Jun 222016 Public
drwxr-xr-x   2 maateen maateen  4096 Apr 262016 Templates
drwxr-xr-x   5 maateen maateen  4096 Dec 2401:26 Videos
drwxrwxr-x 16 maateen maateen  4096 Dec 1420:18 workspace
>>> print(output)
CompletedProcess(args=['ls', '-l'], returncode=0)
>>> import subprocess
>>> output = subprocess.check_output(['ls'])
>>> print(output)
b'Desktop\nDocuments\nDownloads\nMEGAsync\nMusic\nPictures\nPublic\nTemplates\nVideos\nworkspace\n'

রিটার্নকোড জিরো তাই আউটপুট রিটার্ন করেছে, অন্যথায় এক্সেপশন রেইজ করত। আমরা চাইলে run() ফাংশন ব্যবহার করে এই প্রোগ্রামটির একটি ইকুইভ্যালেন্ট (সমতুল্য) প্রোগ্রাম লিখতে পারি। যেমন:

>>> import subprocess
>>> output = subprocess.run(['ls'], check=True, stdout=subprocess.PIPE).stdout
>>> print(output)
b'Desktop\nDocuments\nDownloads\nMEGAsync\nMusic\nPictures\nPublic\nTemplates\nVideos\nworkspace\n'

call()check_call() ফাংশন দুটিতে stdout=PIPEstderr=PIPE ব্যবহার করার ক্ষেত্রে ডেডলক সমস্যার উদগিরণ হলো। সহজ কথায়, ডেডলক হলো এমন একটি পরিস্থিতি যখন প্রসেস-১ রিসোর্স-১ ধরে বসে আছে আর রিসোর্স-২-এর জন্য অপেক্ষা করছে এবং প্রসেস-২ রিসোর্স-২ ধরে বসে আছে আর রিসোর্স-১-এর জন্য অপেক্ষা করছে। যেহেতু একটি রিসোর্স একই সময়ে কেবল একটি প্রসেসকেই অ্যালোকেট করা যায় তাই প্রসেস-১ ও প্রসেস-২ হুদাই বসে থাকবে, কোনো কাজই করতে পারবে না। সাবপ্রসেস মডিউল সম্পর্কে আরও বিস্তারিত জানার জন্য পাইথনের (https://docs.python.org/3/library/subprocess.html) এই অফিশিয়াল ডকুমেন্টেশন থেকে ঘুরে আসতে পারেন।

comments powered by Disqus