subprocess --- مدیریت زیرفرایند¶
کد منبع: Lib/subprocess.py
ماژول subprocess به شما امکان میدهد فرایندهای جدید ایجاد کنید، به پایپهای ورودی/خروجی/خطای آنها متصل شوید و کدهای بازگشت آنها را دریافت کنید. این ماژول قصد دارد جایگزین چندین ماژول و تابع قدیمیتر شود:
os.system
os.spawn*
اطلاعات مربوط به چگونگی استفاده از ماژول subprocess برای جایگزینی این ماژولها و توابع را میتوان در بخشهای زیر یافت.
همچنین ملاحظه نمائید
PEP 324 -- PEP پیشنهادی برای ماژول subprocess
دسترسپذیری: not Android, not iOS, not WASI.
این ماژول در پلتفرمهای موبایل یا پلتفرمهای WebAssembly پشتیبانی نمیشود.
استفاده از ماژول subprocess¶
رویکرد توصیهشده برای فراخوانی زیرفرایندها، استفاده از تابع run() برای تمام موارد استفادهای است که میتواند از عهدهی آنها برآید. برای موارد استفادهی پیشرفتهتر، میتوانید مستقیماً از رابط زیربنایی Popen استفاده کنید.
- subprocess.run(args, *, stdin=None, input=None, stdout=None, stderr=None, capture_output=False, shell=False, cwd=None, timeout=None, check=False, encoding=None, errors=None, text=None, env=None, universal_newlines=None, **other_popen_kwargs)¶
فرمان توصیفشده توسط args را اجرا کنید. منتظر بمانید تا فرمان کامل شود، سپس نمونهای از
CompletedProcessرا برگردانید.آرگومانهای نشاندادهشده در بالا صرفاً رایجترین آرگومانها هستند که در ادامه در آرگومانهای پرکاربرد توضیح داده شدهاند (به همین دلیل از نمادگذاری فقطکلیدواژهای در امضای مختصر استفاده شده است). امضای کامل تابع تا حد زیادی همان امضای سازندهی
Popenاست — بیشتر آرگومانهای این تابع به آن رابط منتقل میشوند. (timeout، input، check و capture_output منتقل نمیشوند.)اگر capture_output مقدار true داشته باشد، stdout و stderr گرفته میشوند. در صورت استفاده، شیء داخلی
Popenبهطور خودکار در حالی ایجاد میشود که stdout و stderr هر دو رویPIPEتنظیم شدهاند. آرگومانهای stdout و stderr نمیتوانند همزمان با capture_output ارائه شوند. اگر میخواهید هر دو جریان را بگیرید و در یک جریان ادغام کنید، بهجای استفاده از capture_output، stdout را رویPIPEو stderr را رویSTDOUTتنظیم کنید.ممکن است یک مهلت بر حسب ثانیه مشخص شود، این مقدار بهصورت داخلی به
Popen.communicate()ارسال میشود. اگر مهلت منقضی شود، فرایند فرزند کشته خواهد شد و برای آن انتظار کشیده خواهد شد. استثنایTimeoutExpiredپس از خاتمه فرایند فرزند دوباره پرتاب خواهد شد. خودِ ایجاد اولیهی فرایند در بسیاری از APIهای پلتفرم قابل وقفه نیست، بنابراین تضمینی وجود ندارد که استثنای مهلت را حداقل تا پس از پایان ایجاد فرایند، هر چقدر هم که طول بکشد، مشاهده کنید.آرگومان input به
Popen.communicate()و در نتیجه به stdin زیرفرایند ارسال میشود. در صورت استفاده، باید دنبالهای از بایتها باشد، یا اگر encoding یا errors مشخص شده باشد یا text درست باشد، یک رشته باشد. هنگام استفاده، شیءPopenداخلی بهطور خودکار با stdin تنظیمشده رویPIPEایجاد میشود، و نمیتوان همزمان از آرگومان stdin نیز استفاده کرد.اگر check درست باشد و فرایند با کد خروجی غیرصفر خارج شود، استثنای
CalledProcessErrorپرتاب خواهد شد. ویژگیهای آن استثنا شامل آرگومانها، کد خروجی، و stdout و stderr هستند، اگر اینها گرفتهشده باشند.اگر encoding یا errors مشخص شده باشند، یا مقدار text درست باشد، اشیای پرونده برای stdin، stdout و stderr در حالت متنی با استفاده از encoding و errors مشخصشده یا پیشفرض
io.TextIOWrapperباز میشوند. آرگومان universal_newlines معادل text است و برای سازگاری با نسخههای پیشین ارائه شده است. بهطور پیشفرض، اشیای پرونده در حالت دودویی باز میشوند.اگر env
Noneنباشد، باید نگاشتی باشد که متغیرهای محیطی فرایند جدید را تعریف میکند؛ این متغیرها به جای رفتار پیشفرضِ به ارث بردن محیط فرایند جاری استفاده میشوند. این نگاشت مستقیماً بهPopenداده میشود. این نگاشت میتواند در هر پلتفرمی از str به str یا در پلتفرمهای POSIX از bytes به bytes باشد، درست مانندos.environیاos.environb.مثالها:
>>> subprocess.run(["ls", "-l"]) # doesn't capture output CompletedProcess(args=['ls', '-l'], returncode=0) >>> subprocess.run("exit 1", shell=True, check=True) Traceback (most recent call last): ... subprocess.CalledProcessError: Command 'exit 1' returned non-zero exit status 1 >>> subprocess.run(["ls", "-l", "/dev/null"], capture_output=True) CompletedProcess(args=['ls', '-l', '/dev/null'], returncode=0, stdout=b'crw-rw-rw- 1 root root 1, 3 Jan 23 16:23 /dev/null\n', stderr=b'')
اضافه شده در نسخهی 3.5.
تغییر یافته در نسخهی 3.6: پارامترهای encoding و errors افزوده شدند
تغییر یافته در نسخهی 3.7: پارامتر text، بهعنوان نام مستعار قابلفهمتر برای universal_newlines، افزوده شد. پارامتر capture_output افزوده شد.
تغییر یافته در نسخهی 3.12: ترتیب جستجوی پوستهی ویندوز برای
shell=Trueتغییر کرد. پوشهی جاری و%PATH%با%COMSPEC%و%SystemRoot%\System32\cmd.exeجایگزین شدهاند. در نتیجه، قرار دادن یک برنامهی مخرب با نامcmd.exeدر پوشهی جاری دیگر کار نمیکند.
- class subprocess.CompletedProcess¶
مقدار بازگشتی از
run()، که نشاندهندهی فرایندی است که به پایان رسیده است.- args¶
آرگومانهای استفادهشده برای راهاندازی فرایند. این ممکن است یک فهرست یا یک رشته باشد.
- returncode¶
وضعیت خروج فرایند فرزند. معمولاً وضعیت خروج ۰ نشان میدهد که با موفقیت اجرا شده است.
یک مقدار منفی
-Nنشان میدهد که فرزند با سیگنالNخاتمه یافته است (فقط POSIX).
- stdout¶
stdout گرفتهشده از فرایند فرزند. دنبالهای از بایتها، یا رشتهای اگر
run()با encoding، errors یا text=True فراخوانی شده باشد. اگر stdout گرفته نشده باشد،Noneاست.اگر فرایند را با
stderr=subprocess.STDOUTاجرا کرده باشید، stdout و stderr در این ویژگی ترکیب میشوند وstderrبرابرNoneخواهد بود.
- stderr¶
stderr گرفتهشده از فرایند فرزند. دنبالهای از بایتها، یا در صورتی که
run()با encoding، errors یا text=True فراخوانی شده باشد، یک رشته است. اگر stderr گرفته نشده باشد،Noneاست.
- check_returncode()¶
اگر
returncodeغیرصفر باشد، یکCalledProcessErrorپرتاب میشود.
اضافه شده در نسخهی 3.5.
- subprocess.DEVNULL¶
مقدار ویژهای که میتواند بهعنوان آرگومان stdin، stdout یا stderr برای
Popenاستفاده شود و نشان میدهد که پرونده ویژهیos.devnullاستفاده خواهد شد.اضافه شده در نسخهی 3.3.
- subprocess.PIPE¶
مقدار ویژهای که میتواند بهعنوان آرگومان stdin، stdout یا stderr برای
Popenاستفاده شود و نشان میدهد که باید یک پایپ به جریان استاندارد باز شود. بیشترین کاربرد را باPopen.communicate()دارد.
- subprocess.STDOUT¶
مقدار ویژهای که میتوان از آن بهعنوان آرگومان stderr برای
Popenاستفاده کرد و نشان میدهد که خطای استاندارد باید به همان دسته خروجی استاندارد برود.
- exception subprocess.SubprocessError¶
کلاس پایه برای همهی استثناهای دیگر این ماژول.
اضافه شده در نسخهی 3.3.
- exception subprocess.TimeoutExpired¶
زیرکلاسی از
SubprocessError، زمانی پرتاب میشود که مهلت در حین انتظار برای یک فرایند فرزند منقضی شود.- cmd¶
فرمانی که برای ایجاد فرآیند فرزند استفاده شده است.
- timeout¶
مهلت زمانی به ثانیه.
- output¶
خروجی فرایند فرزند در صورتی که توسط
run()یاcheck_output()ضبط شده باشد. در غیر این صورت،None. این مقدار هرگاه خروجیای ضبط شده باشد، صرفنظر از تنظیمtext=True، همیشهbytesاست. ممکن است در صورتی که هیچ خروجی مشاهده نشود، بهجایb''همانNoneباقی بماند.
- stderr¶
خروجی stderr فرایند فرزند، در صورتی که توسط
run()گرفته شده باشد. در غیر این صورت،None. این مقدار هر زمان که خروجی stderr گرفته شده باشد، صرفنظر از تنظیمtext=True، همیشهbytesاست. در صورتی که هیچ خروجی stderr مشاهده نشود، ممکن است بهجایb''همانNoneباقی بماند.
اضافه شده در نسخهی 3.3.
تغییر یافته در نسخهی 3.5: ویژگیهای stdout و stderr افزوده شدند
- exception subprocess.CalledProcessError¶
زیرکلاسی از
SubprocessError، زمانی پرتاب میشود که فرایند اجراشده بهوسیلهیcheck_call()،check_output()یاrun()(باcheck=True) وضعیت خروجی غیرصفر برگرداند.- returncode¶
Exit status of the child process, an integer. If the process exited due to a signal, this will be the negative signal number.
- cmd¶
فرمانی که برای ایجاد فرآیند فرزند استفاده شده است.
- output¶
خروجی فرآیند فرزند، اگر توسط
run()یاcheck_output()گرفته شده باشد. در غیر این صورت،None.
تغییر یافته در نسخهی 3.5: ویژگیهای stdout و stderr افزوده شدند
آرگومانهای پرکاربرد¶
برای پشتیبانی از طیف گستردهای از موارد استفاده، سازندهی Popen (و توابع کمکی) تعداد زیادی آرگومان اختیاری میپذیرند. در بیشتر موارد استفادهی معمول، میتوان بسیاری از این آرگومانها را با اطمینان روی مقادیر پیشفرض خود باقی گذاشت. آرگومانهایی که معمولاً بیش از همه مورد نیاز هستند:
args برای همه فراخوانیها لازم است و باید یک رشته یا دنبالهای از آرگومانهای برنامه باشد. ارائه یک دنباله از آرگومانها عموماً ترجیح داده میشود، زیرا به ماژول اجازه میدهد هرگونه خنثیسازی و قرار دادن علامت نقلقول لازم برای آرگومانها را انجام دهد (برای مثال، برای مجاز بودن فاصلهها در نام پروندهها). اگر یک رشته واحد ارسال میکنید، یا shell باید
Trueباشد (در زیر ببینید) یا در غیر این صورت رشته باید صرفاً نام برنامهای را که باید اجرا شود بدون مشخص کردن هیچ آرگومانی بیان کند.stdin، stdout و stderr بهترتیب دستههای پرونده ورودی استاندارد، خروجی استاندارد و خطای استاندارد برنامهی اجراشده را مشخص میکنند. مقادیر معتبر عبارتند از
None،PIPE،DEVNULL، یک توصیفگر پرونده موجود (یک عدد صحیح مثبت) و یک file object موجود با یک توصیفگر پرونده معتبر. با تنظیمات پیشفرضNone، هیچ تغییر مسیری رخ نخواهد داد.PIPEنشان میدهد که باید یک پایپ جدید برای فرآیند فرزند ایجاد شود.DEVNULLنشان میدهد که از پرونده ویژهیos.devnullاستفاده خواهد شد. علاوه بر این، stderr میتواندSTDOUTباشد، که نشان میدهد دادههای stderr از فرآیند فرزند باید در همان دسته پرونده مربوط به stdout دریافت شوند.اگر encoding یا errors مشخص شده باشند، یا text (که با نام universal_newlines نیز شناخته میشود) درست باشد، اشیای پرونده stdin، stdout و stderr در حالت متنی با استفاده از encoding و errors مشخصشده در فراخوان یا پیشفرضهای
io.TextIOWrapperباز خواهند شد.برای stdin، نویسههای پایان خط
'\n'در ورودی به جداکنندهی خط پیشفرضos.linesepتبدیل میشوند. برای stdout و stderr، تمام پایانهای خط در خروجی به'\n'تبدیل میشوند. برای اطلاعات بیشتر، مستندات کلاسio.TextIOWrapperرا برای حالتی که آرگومان newline سازندهی آنNoneاست، ببینید.اگر از حالت متنی استفاده نشود، stdin، stdout و stderr بهعنوان جریانهای دودویی باز خواهند شد. هیچگونه کدگذاری یا تبدیل پایان خط انجام نمیشود.
تغییر یافته در نسخهی 3.6: پارامترهای encoding و errors افزوده شدند.
تغییر یافته در نسخهی 3.7: پارامتر text بهعنوان نام مستعار برای universal_newlines اضافه شد.
توجه
ویژگی newlines اشیای پرونده
Popen.stdin،Popen.stdoutوPopen.stderrتوسط متدPopen.communicate()بهروزرسانی نمیشود.اگر shell برابر
Trueباشد، فرمان مشخصشده از طریق پوسته اجرا میشود. این موضوع میتواند مفید باشد اگر شما از پایتون عمدتاً به دلیل جریان کنترل پیشرفتهتری که نسبت به بیشتر پوستههای سیستم ارائه میدهد استفاده میکنید و همچنان میخواهید دسترسی آسانی به سایر امکانات پوسته داشته باشید، مانند پایپهای پوسته، وایلدکارد نام پرونده، بسط متغیرهای محیطی، و بسط~به پوشهی خانهی کاربر. با این حال، توجه داشته باشید که خود پایتون پیادهسازیهایی از بسیاری از امکانات شبهپوسته ارائه میدهد (بهویژهglob،fnmatch،os.walk()،os.path.expandvars()،os.path.expanduser()وshutil).تغییر یافته در نسخهی 3.3: هنگامی که universal_newlines برابر
Trueباشد، این کلاس بهجایlocale.getpreferredencoding()از کدگذاریlocale.getpreferredencoding(False)استفاده میکند. برای اطلاعات بیشتر درباره این تغییر، کلاسio.TextIOWrapperرا ببینید.توجه
پیش از استفاده از
shell=True، بخش Security Considerations را بخوانید.
این گزینهها، به همراه تمام گزینههای دیگر، با جزئیات بیشتر در مستندات سازندهی Popen توضیح داده شدهاند.
سازنده 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=None, startupinfo=None, creationflags=0, restore_signals=True, start_new_session=False, pass_fds=(), *, group=None, extra_groups=None, user=None, umask=-1, encoding=None, errors=None, text=None, pipesize=-1, process_group=None)¶
یک برنامه فرزند را در یک فرایند جدید اجرا میکند. در POSIX، این کلاس از رفتاری مشابه
os.execvpe()برای اجرای برنامه فرزند استفاده میکند. در ویندوز، این کلاس از تابعCreateProcess()ویندوز استفاده میکند. آرگومانهایPopenبه شرح زیر است.args باید یک دنباله از آرگومانهای برنامه باشد یا در غیر این صورت، یک رشته یا شیء شبهمسیر باشد. بهطور پیشفرض، اگر args یک دنباله باشد، برنامهای که اجرا میشود اولین آیتم در args است. اگر args یک رشته باشد، تفسیر آن وابسته به پلتفرم است و در زیر توضیح داده شده است. برای تفاوتهای بیشتر با رفتار پیشفرض، آرگومانهای shell و executable را ببینید. مگر اینکه خلاف آن ذکر شده باشد، توصیه میشود args را بهعنوان یک دنباله ارسال کنید.
هشدار
برای حداکثر قابلیت اطمینان، از یک مسیر کاملاً مشخص برای پرونده اجرایی استفاده کنید. برای جستوجوی یک نام بدون مسیر در
PATH، ازshutil.which()استفاده کنید. در همهی سکوها، توصیه میشود برای اجرای مجدد مفسر پایتون جاری،sys.executableرا ارسال کنید و برای اجرای یک ماژول نصبشده از قالب خط فرمان-mاستفاده کنید.تعیین مسیر executable (یا اولین آیتم args) وابسته به پلتفرم است. برای POSIX،
os.execvpe()را ببینید، و توجه داشته باشید که هنگام تعیین یا جستوجوی مسیر اجرایی، cwd پوشه کاری فعلی را نادیده میگیرد و env میتواند متغیر محیطیPATHرا نادیده بگیرد. برای ویندوز، مستندات پارامترهایlpApplicationNameوlpCommandLineدر WinAPICreateProcessرا ببینید، و توجه داشته باشید که هنگام تعیین یا جستوجوی مسیر اجرایی باshell=False، cwd پوشه کاری فعلی را نادیده نمیگیرد و env نمیتواند متغیر محیطیPATHرا نادیده بگیرد. استفاده از یک مسیر کامل از تمام این تفاوتها جلوگیری میکند.مثالی از ارسال چند آرگومان به یک برنامه خارجی بهصورت یک دنباله:
Popen(["/usr/bin/git", "commit", "-m", "Fixes a bug."])
در POSIX، اگر args یک رشته باشد، رشته بهعنوان نام یا مسیر برنامه برای اجرا تفسیر میشود. با این حال، این کار تنها در صورتی میتواند انجام شود که آرگومانی به برنامه ارسال نشود.
توجه
ممکن است واضح نباشد که چگونه باید یک فرمان پوسته را به دنبالهای از آرگومانها تجزیه کرد، بهویژه در موارد پیچیده.
shlex.split()میتواند چگونگی تعیین توکنبندی (tokenization) صحیح برای args را نشان دهد:>>> import shlex, subprocess >>> command_line = input() /bin/vikings -input eggs.txt -output "spam spam.txt" -cmd "echo '$MONEY'" >>> args = shlex.split(command_line) >>> print(args) ['/bin/vikings', '-input', 'eggs.txt', '-output', 'spam spam.txt', '-cmd', "echo '$MONEY'"] >>> p = subprocess.Popen(args) # Success!
بهطور خاص توجه داشته باشید که گزینهها (مانند -input) و آرگومانها (مانند eggs.txt) که در پوسته با فضای خالی از هم جدا شدهاند، در عناصر جداگانهای از فهرست قرار میگیرند، در حالی که آرگومانهایی که هنگام استفاده در پوسته به قرارگیری در علامت نقلقول یا خنثیکردن با بکاسلش نیاز دارند (مانند نام پروندههای حاوی فاصله یا فرمان echo که در بالا نشان داده شد)، هرکدام یک عنصر واحد از فهرست هستند.
در ویندوز، اگر args یک دنباله باشد، به شیوهای که در تبدیل دنبالهای از آرگومانها به رشته در ویندوز توضیح داده شده است، به یک رشته تبدیل میشود. این به این دلیل است که
CreateProcess()زیربنایی روی رشتهها عمل میکند.تغییر یافته در نسخهی 3.6: پارامتر args یک path-like object را در صورتی میپذیرد که shell
Falseباشد، و در POSIX دنبالهای حاوی اشیای مسیرمانند (path-like objects) را میپذیرد.تغییر یافته در نسخهی 3.8: پارامتر args یک path-like object را میپذیرد، اگر shell
Falseباشد، و در ویندوز یک دنباله شامل بایتها و اشیاء شبهمسیر را میپذیرد.آرگومان shell (که پیشفرض آن
Falseاست) مشخص میکند که آیا از پوسته بهعنوان برنامه برای اجرا استفاده شود یا خیر. اگر shell برابرTrueباشد، توصیه میشود args را بهصورت یک رشته ارسال کنید، نه بهصورت یک دنباله.در POSIX با
shell=True، پوسته بهطور پیشفرض/bin/shاست. اگر args یک رشته باشد، رشته فرمانی را که باید از طریق پوسته اجرا شود مشخص میکند. این بدان معناست که رشته باید دقیقاً به همان شکلی قالببندی شود که در اعلان پوسته تایپ میشود. این شامل، برای مثال، در علامت نقلقول گذاشتن یا خنثیسازی با بکاسلش نام پروندههایی است که فاصله دارند. اگر args یک دنباله باشد، اولین آیتم رشته فرمان را مشخص میکند و آیتمهای اضافی بهعنوان آرگومانهای اضافی برای خود پوسته در نظر گرفته خواهند شد. یعنیPopenمعادل این کار را انجام میدهد:Popen(['/bin/sh', '-c', args[0], args[1], ...])
در ویندوز با
shell=True، متغیر محیطیCOMSPECپوسته پیشفرض را مشخص میکند. تنها زمانی نیاز استshell=Trueرا در ویندوز مشخص کنید که فرمانی که میخواهید اجرا کنید در پوسته توکار باشد (مانند dir یا copy). برای اجرای یک پرونده batch یا پرونده اجرایی مبتنی بر کنسول نیازی بهshell=Trueندارید.توجه
پیش از استفاده از
shell=True، بخش Security Considerations را بخوانید.هنگام ایجاد اشیاء پرونده پایپ stdin/stdout/stderr، bufsize بهعنوان آرگومان متناظر به تابع
open()داده میشود:0به معنای بدون بافر است (خواندن و نوشتن هرکدام یک فراخوانی سیستمی هستند و ممکن است مقدار کمتری برگردانند)1بهمعنای بافر سطری (line buffered) است (فقط در صورتی قابلاستفاده است کهtext=Trueیاuniversal_newlines=Trueباشد).هر مقدار مثبت دیگر به معنای استفاده از بافری با اندازهای تقریباً برابر با آن مقدار است
منفی بودن bufsize (حالت پیشفرض) به این معناست که پیشفرض سیستم، یعنی io.DEFAULT_BUFFER_SIZE، استفاده خواهد شد.
تغییر یافته در نسخهی 3.3.1: مقدار پیشفرض bufsize اکنون -1 است تا بافرینگ (buffering) بهصورت پیشفرض فعال شود و با رفتاری که بیشتر کدها انتظار دارند مطابقت داشته باشد. در نسخههای پیش از پایتون 3.2.4 و 3.3.1، مقدار پیشفرض آن بهاشتباه
0بود که بدون بافرینگ بود و امکان خواندنهای کوتاه (short reads) را فراهم میکرد. این موضوع غیرعمدی بود و با رفتار پایتون 2، آنگونه که بیشتر کدها انتظار داشتند، مطابقت نداشت.آرگومان executable برنامه جایگزینی را برای اجرا مشخص میکند. بهندرت به آن نیاز است. هنگامی که
shell=Falseباشد، executable جایگزین برنامهای میشود که توسط args برای اجرا مشخص شده است. با این حال، args اصلی همچنان به برنامه ارسال میشود. بیشتر برنامهها برنامه مشخصشده توسط args را بهعنوان نام فرمان تلقی میکنند، که در این صورت میتواند با برنامهای که واقعاً اجرا میشود متفاوت باشد. در POSIX، نام args به نام نمایشی برنامه اجرایی در ابزارهایی مانند ps تبدیل میشود. اگرshell=Trueباشد، در POSIX آرگومان executable پوسته جایگزینی را بهجای پوسته پیشفرض/bin/shمشخص میکند.تغییر یافته در نسخهی 3.6: در POSIX، پارامتر executable یک path-like object را میپذیرد.
تغییر یافته در نسخهی 3.8: در ویندوز، پارامتر executable یک bytes و یک path-like object را میپذیرد.
تغییر یافته در نسخهی 3.12: ترتیب جستجوی پوستهی ویندوز برای
shell=Trueتغییر کرد. پوشهی جاری و%PATH%با%COMSPEC%و%SystemRoot%\System32\cmd.exeجایگزین شدهاند. در نتیجه، قرار دادن یک برنامهی مخرب با نامcmd.exeدر پوشهی جاری دیگر کار نمیکند.stdin، stdout و stderr بهترتیب دستههای پرونده ورودی استاندارد، خروجی استاندارد و خطای استاندارد برنامهی اجراشده را تعیین میکنند. مقادیر معتبر عبارتاند از
None،PIPE،DEVNULL، یک توصیفگر پرونده موجود (یک عدد صحیح مثبت)، و یک file object موجود با یک توصیفگر پرونده معتبر. با تنظیمات پیشفرضNone، هیچ تغییر مسیری رخ نخواهد داد.PIPEنشان میدهد که باید یک پایپ جدید به فرزند ایجاد شود.DEVNULLنشان میدهد که از پرونده ویژهیos.devnullاستفاده خواهد شد. علاوه بر این، stderr میتواندSTDOUTباشد، که نشان میدهد دادههای stderr برنامهها باید در همان دسته پرونده مربوط به stdout دریافت شوند.اگر preexec_fn به یک شیء فراخوانیپذیر تنظیم شود، این شیء در فرآیند فرزند درست پیش از اجرای فرزند فراخوانی میشود. (فقط POSIX)
هشدار
استفاده از پارامتر preexec_fn در حضور نخها در برنامه شما ایمن نیست. فرآیند فرزند ممکن است پیش از فراخوانی exec دچار بنبست شود.
توجه
اگر نیاز دارید محیط فرزند را تغییر دهید، بهجای انجام این کار در preexec_fn از پارامتر env استفاده کنید. پارامترهای start_new_session و process_group باید جایگزین کدی شوند که از preexec_fn برای فراخوانی
os.setsid()یاos.setpgid()در فرزند استفاده میکند.تغییر یافته در نسخهی 3.8: پارامتر preexec_fn دیگر در زیرمفسرها پشتیبانی نمیشود. استفاده از این پارامتر در یک زیرمفسر باعث پرتاب
RuntimeErrorمیشود. این محدودیت جدید ممکن است بر برنامههایی که در mod_wsgi، uWSGI و سایر محیطهای تعبیهشده مستقر شدهاند تأثیر بگذارد.اگر close_fds درست باشد، تمام توصیفگرهای پرونده به جز
0،1و2پیش از اجرای فرایند فرزند بسته میشوند. در غیر این صورت، هنگامی که close_fds نادرست باشد، توصیفگرهای پرونده مطابق پرچم ارثی خود رفتار میکنند، همانطور که در وراثت توصیفگرهای پرونده توضیح داده شده است.در ویندوز، اگر close_fds درست باشد، هیچ دستهای توسط فرایند فرزند به ارث برده نمیشود، مگر آنکه بهصراحت در عنصر
handle_listازSTARTUPINFO.lpAttributeListیا از طریق هدایت مجدد دسته استاندارد منتقل شده باشد.تغییر یافته در نسخهی 3.2: مقدار پیشفرض برای close_fds از
Falseبه آنچه در بالا توضیح داده شد تغییر کرده است.تغییر یافته در نسخهی 3.7: در ویندوز، مقدار پیشفرض برای close_fds هنگام تغییر مسیر دستههای استاندارد (standard handles) از
FalseبهTrueتغییر کرد. اکنون میتوانید close_fds را هنگام تغییر مسیر دستههای استاندارد (standard handles) رویTrueتنظیم کنید.pass_fds دنبالهای اختیاری از توصیفگرهای پرونده است که باید بین والد و فرزند باز نگه داشته شوند. ارائه هر pass_fds، close_fds را مجبور میکند که
Trueباشد. (فقط POSIX)تغییر یافته در نسخهی 3.2: پارامتر pass_fds اضافه شد.
اگر cwd برابر
Noneنباشد، تابع پیش از اجرای فرزند، پوشه کاری را به cwd تغییر میدهد. cwd میتواند یک رشته، bytes یا شیء path-like باشد. در POSIX، اگر مسیر اجرایی یک مسیر نسبی باشد، تابع executable (یا اولین آیتم در args) را نسبت به cwd جستوجو میکند.تغییر یافته در نسخهی 3.6: پارامتر cwd در POSIX یک path-like object را میپذیرد.
تغییر یافته در نسخهی 3.7: در ویندوز، پارامتر cwd یک path-like object را میپذیرد.
تغییر یافته در نسخهی 3.8: پارامتر cwd در ویندوز یک شیء bytes را میپذیرد.
اگر restore_signals صحیح باشد (پیشفرض)، همه سیگنالهایی که پایتون آنها را روی SIG_IGN تنظیم کرده است، در فرایند فرزند پیش از exec به SIG_DFL بازنشانی میشوند. در حال حاضر این شامل سیگنالهای SIGPIPE، SIGXFZ و SIGXFSZ میشود. (فقط POSIX)
تغییر یافته در نسخهی 3.2: restore_signals افزوده شد.
اگر start_new_session مقدار true داشته باشد، فراخوانی سیستمی
setsid()در فرایند فرزند پیش از اجرای زیرفرایند انجام میشود.دسترسپذیری: POSIX
تغییر یافته در نسخهی 3.2: start_new_session افزوده شد.
اگر process_group یک عدد صحیح غیرمنفی باشد، فراخوانی سیستمی
setpgid(0, value)در فرایند فرزند پیش از اجرای زیرفرایند انجام خواهد شد.دسترسپذیری: POSIX
تغییر یافته در نسخهی 3.11: process_group اضافه شد.
اگر group برابر
Noneنباشد، فراخوانی سیستمی setregid() در فرایند فرزند پیش از اجرای زیرفرایند انجام خواهد شد. اگر مقدار ارائهشده یک رشته باشد، از طریقgrp.getgrnam()جستجو خواهد شد و از مقدار موجود درgr_gidاستفاده خواهد شد. اگر مقدار یک عدد صحیح باشد، عیناً ارسال خواهد شد. (فقط POSIX)دسترسپذیری: POSIX
اضافه شده در نسخهی 3.9.
اگر extra_groups برابر
Noneنباشد، فراخوانی سیستمی setgroups() پیش از اجرای زیرفرآیند در فرآیند فرزند انجام خواهد شد. رشتههای ارائهشده در extra_groups با استفاده ازgrp.getgrnam()جستجو خواهند شد و مقادیر موجود درgr_gidبه کار خواهند رفت. مقادیر عدد صحیح عیناً ارسال خواهند شد. (فقط POSIX)دسترسپذیری: POSIX
اضافه شده در نسخهی 3.9.
اگر user برابر
Noneنباشد، فراخوانی سیستمی setreuid() در فرایند فرزند پیش از اجرای زیرفرایند انجام میشود. اگر مقدار ارائهشده یک رشته باشد، از طریقpwd.getpwnam()جستجو میشود و از مقدارpw_uidاستفاده میشود. اگر مقدار یک عدد صحیح باشد، عیناً ارسال میشود. (فقط POSIX)توجه
تعیین user، عضویتهای گروه تکمیلی موجود را حذف نمیکند! فراخواننده همچنین باید
extra_groups=()را ارسال کند تا عضویت گروه فرایند فرزند را برای اهداف امنیتی کاهش دهد.دسترسپذیری: POSIX
اضافه شده در نسخهی 3.9.
اگر umask منفی نباشد، فراخوانی سیستمی umask() پیش از اجرای زیرفرایند، در فرایند فرزند انجام میشود.
دسترسپذیری: POSIX
اضافه شده در نسخهی 3.9.
اگر env برابر
Noneنباشد، باید یک نگاشت باشد که متغیرهای محیطی فرایند جدید را تعریف میکند؛ این متغیرها به جای رفتار پیشفرضِ به ارث بردن محیط فرایند جاری استفاده میشوند. این نگاشت میتواند در هر پلتفرمی از str به str یا در پلتفرمهای POSIX از bytes به bytes باشد، درست مانندos.environیاos.environb.توجه
اگر مشخص شده باشد، env باید هر متغیر مورد نیاز برای اجرای برنامه را فراهم کند. در ویندوز، برای اجرای یک side-by-side assembly، env مشخصشده باید شامل یک
%SystemRoot%معتبر باشد.اگر encoding یا errors مشخص شده باشند، یا text true باشد، اشیای پرونده stdin، stdout و stderr در حالت متنی با encoding و errors مشخصشده باز میشوند، همانطور که در بالا در آرگومانهای پرکاربرد توضیح داده شده است. آرگومان universal_newlines معادل text است و برای سازگاری با نسخههای پیشین ارائه شده است. بهطور پیشفرض، اشیای پرونده در حالت دودویی باز میشوند.
اضافه شده در نسخهی 3.6: encoding و errors اضافه شدند.
اضافه شده در نسخهی 3.7: text بهعنوان نام مستعاری خواناتر برای universal_newlines افزوده شد.
در صورت داده شدن، startupinfo یک شیء
STARTUPINFOخواهد بود که به تابع زیرساختیCreateProcessارسال میشود.در صورت ارائه شدن، creationflags میتواند یک یا چند مورد از پرچمهای زیر باشد:
میتوان از pipesize برای تغییر اندازهی پایپ هنگامی که از
PIPEبرای stdin، stdout یا stderr استفاده میشود، استفاده کرد. اندازهی پایپ فقط در سکوهایی که از این قابلیت پشتیبانی میکنند تغییر میکند (در زمان نگارش این متن، فقط لینوکس). سایر سکوها این پارامتر را نادیده میگیرند.تغییر یافته در نسخهی 3.10: پارامتر pipesize افزوده شد.
اشیاء Popen بهعنوان مدیر زمینه از طریق دستور
withپشتیبانی میشوند: در هنگام خروج، توصیفگرهای پرونده استاندارد بسته میشوند و برای فرایند انتظار کشیده میشود.with Popen(["ifconfig"], stdout=PIPE) as proc: log.write(proc.stdout.read())
Popen و سایر توابع این ماژول که از آن استفاده میکنند، یک رویداد حسابرسی
subprocess.Popenرا با آرگومانهایexecutable،args،cwdوenvپرتاب میکنند. بسته به سکو، مقدارargsممکن است یک رشته منفرد یا فهرستی از رشتهها باشد.تغییر یافته در نسخهی 3.2: پشتیبانی از مدیر زمینه اضافه شد.
تغییر یافته در نسخهی 3.6: تخریبکنندهی Popen اکنون در صورتی که فرایند فرزند هنوز در حال اجرا باشد، یک هشدار
ResourceWarningنشان میدهد.تغییر یافته در نسخهی 3.8: Popen میتواند در برخی موارد برای عملکرد بهتر از
os.posix_spawn()استفاده کند. در Windows Subsystem for Linux و QEMU User Emulation، سازندهی Popen هنگام استفاده ازos.posix_spawn()دیگر در صورت بروز خطاهایی مانند نبود برنامه استثنا پرتاب نمیکند، اما فرآیند فرزند باreturncodeغیرصفر شکست میخورد.
استثناها¶
استثناهای پرتابشده در فرایند فرزند، پیش از شروع اجرای برنامه جدید، در فرایند والد دوباره پرتاب خواهند شد.
رایجترین استثنایی که پرتاب میشود، OSError است. این استثنا، برای مثال، هنگام تلاش برای اجرای پروندهای ناموجود رخ میدهد. برنامهها باید برای استثناهای OSError آماده باشند. توجه داشته باشید که وقتی shell=True باشد، OSError تنها در صورتی توسط فرایند فرزند پرتاب خواهد شد که خود پوسته انتخابشده یافت نشود. برای تشخیص اینکه پوسته در پیدا کردن برنامه درخواستشده ناموفق بوده است، لازم است کد بازگشتی یا خروجی زیرفرایند بررسی شود.
اگر Popen با آرگومانهای نامعتبر فراخوانی شود، استثنای ValueError پرتاب میشود.
check_call() و check_output() در صورتی که فرایند فراخوانیشده یک کد بازگشت غیرصفر برگرداند، CalledProcessError را پرتاب میکنند.
تمام توابع و متدهایی که پارامتر timeout را میپذیرند، مانند run() و Popen.communicate()، اگر مهلت زمانی پیش از خروج فرایند منقضی شود، استثنای TimeoutExpired را پرتاب میکنند.
تمام استثناهای تعریفشده در این ماژول از SubprocessError ارث میبرند.
اضافه شده در نسخهی 3.3: کلاس پایه SubprocessError افزوده شد.
ملاحظات امنیتی¶
برخلاف برخی دیگر از توابع popen، این کتابخانه بهطور ضمنی انتخاب نمیکند که یک پوستهی سیستم را فراخوانی کند. این بدان معناست که همهی نویسهها، از جمله فرانویسههای پوسته، میتوانند بهصورت امن به فرآیندهای فرزند ارسال شوند. اگر پوسته بهطور صریح از طریق shell=True فراخوانی شود، بر عهدهی برنامه است که اطمینان حاصل کند همهی نویسههای فاصله و فرانویسهها بهشکل مناسب داخل علامت نقلقول قرار گرفتهاند تا از آسیبپذیریهای تزریق پوسته جلوگیری شود. در برخی سکوها، میتوان برای این خنثیسازی از shlex.quote() استفاده کرد.
در ویندوز، پروندههای دستهای (*.bat یا *.cmd) ممکن است توسط سیستمعامل در پوستهی سیستم اجرا شوند، صرفنظر از آرگومانهای دادهشده به این کتابخانه. این میتواند باعث شود که آرگومانها بر اساس قوانین پوسته تجزیه شوند، اما بدون اینکه پایتون هیچگونه خنثیسازیای اضافه کرده باشد. اگر عمداً در حال اجرای یک پرونده دستهای با آرگومانهایی از منابع نامطمئن هستید، پاس دادن shell=True را در نظر داشته باشید تا پایتون بتواند نویسههای خاص را خنثی کند. برای بحث بیشتر gh-114539 را ببینید.
اشیای Popen¶
نمونههای کلاس Popen دارای متدهای زیر هستند:
- Popen.poll()¶
بررسی میکند که آیا فرایند فرزند خاتمه یافته است. ویژگی
returncodeرا تنظیم میکند و برمیگرداند. در غیر این صورت،Noneرا برمیگرداند.
- Popen.wait(timeout=None)¶
منتظر میماند تا فرایند فرزند خاتمه یابد. ویژگی
returncodeرا تنظیم و برمیگرداند.اگر فرایند پس از timeout ثانیه به پایان نرسد، استثنای
TimeoutExpiredپرتاب میشود. گرفتن این استثنا و تلاش مجدد برای انتظار ایمن است.توجه
هنگام استفاده از
stdout=PIPEیاstderr=PIPE، اگر فرایند فرزند آنقدر خروجی به یک پایپ تولید کند که در انتظار پذیرش دادههای بیشتر توسط بافر پایپ سیستمعامل مسدود شود، بنبست رخ خواهد داد. برای جلوگیری از این حالت، هنگام استفاده از پایپها ازPopen.communicate()استفاده کنید.توجه
هنگامی که پارامتر
timeoutبرابرNoneنباشد، در این صورت (در POSIX) این تابع با استفاده از یک حلقهی مشغول (busy loop) پیادهسازی میشود (فراخوانی غیرمسدودکننده و توقفهای کوتاه). برای انتظار ناهمگام، از ماژولasyncioاستفاده کنید:asyncio.create_subprocess_execرا ببینید.تغییر یافته در نسخهی 3.3: timeout افزوده شد.
- Popen.communicate(input=None, timeout=None)¶
با فرایند تعامل میکند: دادهها را به stdin ارسال میکند. دادهها را از stdout و stderr میخواند، تا به پایان پرونده برسد. منتظر میماند تا فرایند خاتمه یابد و ویژگی
returncodeرا تنظیم میکند. آرگومان اختیاری input باید دادهای برای ارسال به فرایند فرزند باشد، یاNone، اگر نباید هیچ دادهای به فرایند فرزند ارسال شود. اگر جریانها در حالت متنی باز شده باشند، input باید یک رشته باشد. در غیر این صورت، باید bytes باشد.communicate()یک تاپل(stdout_data, stderr_data)را برمیگرداند. اگر جریانها در حالت متنی باز شده باشند، دادهها رشته خواهند بود؛ در غیر این صورت، بایت خواهند بود.توجه داشته باشید که اگر میخواهید دادهای را به stdin فرایند ارسال کنید، باید شیء Popen را با
stdin=PIPEایجاد کنید. بهطور مشابه، برای دریافت هر مقداری غیر ازNoneدر تاپل نتیجه، بایدstdout=PIPEو/یاstderr=PIPEرا نیز مشخص کنید.اگر فرآیند پس از timeout ثانیه خاتمه نیابد، استثنای
TimeoutExpiredپرتاب خواهد شد. گرفتن این استثنا و تلاش مجدد برای ارتباط، باعث از دست رفتن هیچ خروجی نخواهد شد. ارائه input به یک فراخوانیcommunicate()بعدی پس از انقضای مهلت، رفتار تعریفنشدهای دارد و ممکن است در آینده به خطا تبدیل شود.اگر مهلت به پایان برسد، فرایند فرزند کشته نمیشود، بنابراین برای پاکسازی صحیح، برنامهای که رفتار درستی دارد باید فرایند فرزند را بکشد و ارتباط را پایان دهد:
proc = subprocess.Popen(...) try: outs, errs = proc.communicate(timeout=15) except TimeoutExpired: proc.kill() outs, errs = proc.communicate()
پس از آنکه فراخوانی
communicate()منجر به پرتابTimeoutExpiredشد،wait()را فراخوانی نکنید. برای به پایان رساندن پردازش پایپها و مقداردهی ویژگیreturncode، یک فراخوانی اضافی ازcommunicate()انجام دهید.توجه
دادهی خواندهشده در حافظه بافر میشود، بنابراین اگر اندازهی داده زیاد یا نامحدود است، از این متد استفاده نکنید.
تغییر یافته در نسخهی 3.3: timeout افزوده شد.
- Popen.send_signal(signal)¶
سیگنال signal را به فرزند ارسال میکند.
اگر فرایند تکمیل شد، هیچ کاری انجام ندهید.
توجه
در ویندوز، SIGTERM نام مستعاری برای
terminate()است. میتوان CTRL_C_EVENT و CTRL_BREAK_EVENT را به فرایندهایی که با پارامتر creationflags شاملCREATE_NEW_PROCESS_GROUPآغاز شدهاند، ارسال کرد.
- Popen.terminate()¶
فرزند را متوقف میکند. در سیستمعاملهای POSIX، این متد
SIGTERMرا به فرزند ارسال میکند. در ویندوز، تابعTerminateProcess()از API Win32 برای توقف فرزند فراخوانی میشود.
- Popen.kill()¶
فرزند را میکشد. در سیستمعاملهای POSIX، این تابع SIGKILL را به فرزند ارسال میکند. در ویندوز،
kill()نام مستعاری برایterminate()است.
ویژگیهای زیر نیز توسط کلاس تنظیم میشوند تا شما به آنها دسترسی داشته باشید. انتساب مجدد آنها به مقادیر جدید پشتیبانی نمیشود:
- Popen.args¶
آرگومان args همانگونه که به
Popenفرستاده شده است -- دنبالهای از آرگومانهای برنامه یا یک رشته.اضافه شده در نسخهی 3.3.
- Popen.stdin¶
اگر آرگومان stdin برابر
PIPEبود، این ویژگی یک شیء جریان قابلنوشتن است، همانند شیء برگرداندهشده توسطopen(). اگر آرگومانهای encoding یا errors مشخص شده باشند یا آرگومان text یا آرگومان universal_newlines برابرTrueباشد، جریان یک جریان متنی است، در غیر این صورت یک جریان بایتی است. اگر آرگومان stdin برابرPIPEنبود، این ویژگیNoneاست.
- Popen.stdout¶
اگر آرگومان stdout برابر
PIPEبود، این ویژگی یک شیء جریان خواندنی است، مانند شیء بازگرداندهشده توسطopen(). خواندن از جریان، خروجی فرایند فرزند را فراهم میکند. اگر آرگومانهای encoding یا errors مشخص شده باشند یا آرگومان text یا universal_newlines برابرTrueباشد، جریان یک جریان متنی است، در غیر این صورت یک جریان بایتی است. اگر آرگومان stdout برابرPIPEنبود، این ویژگیNoneاست.
- Popen.stderr¶
اگر آرگومان stderr برابر
PIPEباشد، این ویژگی یک شیء جریان خواندنی است، مانند شیءای کهopen()بازمیگرداند. خواندن از جریان، خروجی خطای فرایند فرزند را فراهم میکند. اگر آرگومانهای encoding یا errors تعیینشده باشند یا آرگومان text یا universal_newlines برابرTrueباشد، جریان یک جریان متنی است، در غیر این صورت یک جریان بایتی است. اگر آرگومان stderr برابرPIPEنباشد، این ویژگیNoneاست.
هشدار
برای جلوگیری از بنبستهای ناشی از پر شدن هر یک از سایر بافرهای پایپ سیستمعامل و مسدود شدن فرایند فرزند، از communicate() به جای .stdin.write، .stdout.read یا .stderr.read استفاده کنید.
- Popen.pid¶
شناسه فرایند فرزند.
توجه داشته باشید که اگر آرگومان shell را روی
Trueتنظیم کنید، این شناسه فرایند پوسته ایجادشده است.
- Popen.returncode¶
کد بازگشت فرزند.
returncodeکه در ابتداNoneاست، در صورتی با فراخوانی متدهایpoll()،wait()یاcommunicate()تنظیم میشود که این متدها تشخیص دهند فرایند خاتمه یافته است.مقدار
Noneنشان میدهد که فرایند در زمان آخرین فراخوانی متد هنوز خاتمه نیافته بود.یک مقدار منفی
-Nنشان میدهد که فرزند با سیگنالNخاتمه یافته است (فقط POSIX).هنگامی که
shell=Trueباشد، کد بازگشتی وضعیت خروج خود پوسته (برای مثال/bin/sh) را منعکس میکند، که ممکن است سیگنالها را به کدهایی مانند128+Nنگاشت کند. برای جزئیات، مستندات پوسته (برای مثال، بخش Exit Status راهنمای Bash) را ببینید.
کمکیهای Popen در ویندوز¶
کلاس STARTUPINFO و ثابتهای زیر فقط در ویندوز در دسترس هستند.
- class subprocess.STARTUPINFO(*, dwFlags=0, hStdInput=None, hStdOutput=None, hStdError=None, wShowWindow=0, lpAttributeList=None)¶
پشتیبانی جزئی از ساختار STARTUPINFO ویندوز برای ایجاد
Popenاستفاده میشود. ویژگیهای زیر را میتوان با ارسال آنها بهعنوان آرگومانهای فقط کلیدواژهای تنظیم کرد.تغییر یافته در نسخهی 3.7: پشتیبانی از آرگومانهای فقط کلیدواژهای افزوده شد.
- dwFlags¶
یک میدان بیتی (bit field) که تعیین میکند آیا برخی ویژگیهای
STARTUPINFOهنگام ایجاد پنجره توسط فرایند استفاده میشوند یا خیر.si = subprocess.STARTUPINFO() si.dwFlags = subprocess.STARTF_USESTDHANDLES | subprocess.STARTF_USESHOWWINDOW
- hStdInput¶
اگر
dwFlagsSTARTF_USESTDHANDLESرا مشخص کند، این ویژگی، دسته ورودی استاندارد فرایند است. اگرSTARTF_USESTDHANDLESمشخص نشده باشد، پیشفرض ورودی استاندارد، بافر صفحهکلید است.
- hStdOutput¶
اگر
dwFlagsمقدارSTARTF_USESTDHANDLESرا مشخص کند، این ویژگی، دسته خروجی استاندارد فرایند است. در غیر این صورت، این ویژگی نادیده گرفته میشود و پیشفرض خروجی استاندارد، بافر پنجرهی کنسول است.
- hStdError¶
اگر
dwFlagsمقدارSTARTF_USESTDHANDLESرا تعیین کند، این ویژگی، دسته خطای استاندارد برای فرایند است. در غیر این صورت، این ویژگی نادیده گرفته میشود و پیشفرض برای خطای استاندارد، بافر پنجرهی کنسول است.
- wShowWindow¶
اگر
dwFlagsمقدارSTARTF_USESHOWWINDOWرا مشخص کند، این ویژگی میتواند هر یک از مقدارهایی باشد که میتوان در پارامترnCmdShowبرای تابع ShowWindow مشخص کرد، بهجزSW_SHOWDEFAULT. در غیر این صورت، این ویژگی نادیده گرفته میشود.SW_HIDEبرای این ویژگی در نظر گرفته شده است. این مقدار زمانی استفاده میشود کهPopenباshell=Trueفراخوانی شود.
- lpAttributeList¶
یک دیکشنری از ویژگیهای اضافی برای ایجاد فرایند، همانطور که در
STARTUPINFOEXآمده است؛ UpdateProcThreadAttribute را ببینید.ویژگیهای پشتیبانیشده:
- handle_list
دنبالهای از دستهها که به ارث برده خواهند شد. close_fds باید در صورت غیرخالی بودن، true باشد.
دستهها باید هنگام ارسال به سازندهی
Popen، بهطور موقت با استفاده ازos.set_handle_inheritable()قابلارثبردن شوند، در غیر این صورتOSErrorبا خطای ویندوزERROR_INVALID_PARAMETER(87) پرتاب خواهد شد.هشدار
در یک فرایند چندنخی، هنگام ترکیب این قابلیت با فراخوانیهای همزمان به دیگر توابع ایجاد فرایند، مانند
os.system()، که همهی دستهها را به ارث میبرند، احتیاط کنید تا از نشت دستههایی که بهعنوان قابل ارثبری علامتگذاری شدهاند جلوگیری شود. این موضوع در مورد تغییر مسیر دستههای استاندارد نیز صدق میکند، که بهطور موقت دستههای قابل ارثبری ایجاد میکند.
اضافه شده در نسخهی 3.7.
ثابتهای ویندوز¶
ماژول subprocess ثابتهای زیر را ارائه میدهد.
- subprocess.STD_INPUT_HANDLE¶
دستگاه ورودی استاندارد. در ابتدا، این بافر ورودی کنسول،
CONIN$است.
- subprocess.STD_OUTPUT_HANDLE¶
دستگاه خروجی استاندارد. در ابتدا، این بافر صفحهی کنسول فعال،
CONOUT$است.
- subprocess.STD_ERROR_HANDLE¶
دستگاه خطای استاندارد. در ابتدا، این بافر صفحهی کنسول فعال است،
CONOUT$.
- subprocess.SW_HIDE¶
پنجره را پنهان میکند. پنجرهای دیگر فعال خواهد شد.
- subprocess.STARTF_USESTDHANDLES¶
مشخص میکند که ویژگیهای
STARTUPINFO.hStdInput،STARTUPINFO.hStdOutputوSTARTUPINFO.hStdErrorحاوی اطلاعات اضافی هستند.
- subprocess.STARTF_USESHOWWINDOW¶
مشخص میکند که ویژگی
STARTUPINFO.wShowWindowشامل اطلاعات اضافی است.
- subprocess.STARTF_FORCEONFEEDBACK¶
پارامتری برای
STARTUPINFO.dwFlagsجهت تعیین اینکه مکاننما ماوس در حال کار در پسزمینه در حین راهاندازی یک فرآیند نمایش داده خواهد شد. این رفتار پیشفرض برای فرآیندهای GUI است.اضافه شده در نسخهی 3.13.
- subprocess.STARTF_FORCEOFFFEEDBACK¶
یک پارامتر
STARTUPINFO.dwFlagsبرای مشخص کردن اینکه مکاننما ماوس هنگام راهاندازی یک فرایند تغییر نخواهد کرد.اضافه شده در نسخهی 3.13.
- subprocess.CREATE_NEW_CONSOLE¶
فرایند جدید، بهجای به ارث بردن کنسول فرایند والد خود (حالت پیشفرض)، یک کنسول جدید دارد.
- subprocess.CREATE_NEW_PROCESS_GROUP¶
یک پارامتر
creationflagsبرایPopenجهت مشخص کردن اینکه یک گروه فرایند جدید ایجاد میشود. این پرچم برای استفاده ازos.kill()روی زیرفرایند ضروری است.اگر
CREATE_NEW_CONSOLEمشخص شده باشد، این پرچم نادیده گرفته میشود.
- subprocess.ABOVE_NORMAL_PRIORITY_CLASS¶
یک پارامتر
creationflagsبرایPopenجهت مشخص کردن اینکه فرایند جدید اولویتی بالاتر از میانگین خواهد داشت.اضافه شده در نسخهی 3.7.
- subprocess.BELOW_NORMAL_PRIORITY_CLASS¶
پارامتر
creationflagsبرایPopenجهت مشخص کردن اینکه یک فرایند جدید اولویتی کمتر از میانگین خواهد داشت.اضافه شده در نسخهی 3.7.
- subprocess.HIGH_PRIORITY_CLASS¶
یک پارامتر
creationflagsبرایPopenجهت مشخص کردن اینکه یک فرایند جدید اولویت بالایی خواهد داشت.اضافه شده در نسخهی 3.7.
- subprocess.IDLE_PRIORITY_CLASS¶
یک پارامتر
creationflagsبرایPopenجهت مشخص کردن اینکه یک فرایند جدید اولویت بیکار (کمترین) را خواهد داشت.اضافه شده در نسخهی 3.7.
- subprocess.NORMAL_PRIORITY_CLASS¶
یک پارامتر
creationflagsبرایPopenجهت مشخص کردن اینکه یک فرایند جدید اولویت عادی خواهد داشت. (پیشفرض)اضافه شده در نسخهی 3.7.
- subprocess.REALTIME_PRIORITY_CLASS¶
یک پارامتر
creationflagsبرایPopenجهت مشخص کردن اینکه یک فرایند جدید اولویت بلادرنگ خواهد داشت. شما تقریباً هرگز نباید از REALTIME_PRIORITY_CLASS استفاده کنید، زیرا این کار در نخهای سیستمی که ورودی ماوس، ورودی صفحهکلید و تخلیه دیسک در پسزمینه را مدیریت میکنند وقفه میاندازد. این کلاس میتواند برای برنامههایی که مستقیماً با سختافزار «صحبت» میکنند یا وظایف کوتاهمدتی را انجام میدهند که باید وقفههای محدودی داشته باشند، مناسب باشد.اضافه شده در نسخهی 3.7.
- subprocess.CREATE_NO_WINDOW¶
یک پارامتر
creationflagsبرایPopenجهت مشخص کردن اینکه یک فرایند جدید پنجرهای ایجاد نمیکند.اضافه شده در نسخهی 3.7.
- subprocess.DETACHED_PROCESS¶
یک پارامتر
creationflagsبرایPopenکه مشخص میکند فرایند جدید، کنسول والد خود را به ارث نخواهد برد. این مقدار نمیتواند همراه با CREATE_NEW_CONSOLE استفاده شود.اضافه شده در نسخهی 3.7.
- subprocess.CREATE_DEFAULT_ERROR_MODE¶
یک پارامتر
creationflagsبرایPopenتا مشخص کند که فرایند جدید، حالت خطای فرایند فراخواننده را به ارث نمیبرد. در عوض، فرایند جدید حالت خطای پیشفرض را دریافت میکند. این قابلیت بهویژه برای برنامههای پوستهای چندنخی مفید است که با خطاهای سخت غیرفعال اجرا میشوند.اضافه شده در نسخهی 3.7.
API سطح بالای قدیمیتر¶
پیش از پایتون 3.5، این سه تابع API سطحبالا برای subprocess را تشکیل میدادند. اکنون میتوانید در بسیاری از موارد از run() استفاده کنید، اما بسیاری از کدهای موجود این توابع را فراخوانی میکنند.
- subprocess.call(args, *, stdin=None, stdout=None, stderr=None, shell=False, cwd=None, timeout=None, **other_popen_kwargs)¶
فرمان مشخصشده با args را اجرا کنید. منتظر بمانید تا فرمان کامل شود، سپس ویژگی
returncodeرا برگردانید.کدی که نیاز به گرفتن stdout یا stderr دارد، باید بهجای آن از
run()استفاده کند:run(...).returncode
برای سرکوب stdout یا stderr، مقدار
DEVNULLرا ارائه دهید.آرگومانهای نشاندادهشده در بالا تنها چند مورد رایج هستند. امضای کامل تابع همانند امضای سازندهی
Popenاست؛ این تابع تمام آرگومانهای ارائهشده بهجز timeout را مستقیماً به آن رابط منتقل میکند.توجه
از
stdout=PIPEیاstderr=PIPEبا این تابع استفاده نکنید. اگر فرایند فرزند به اندازهای خروجی به یک پایپ تولید کند که بافر پایپ سیستمعامل (OS pipe buffer) را پر کند، مسدود خواهد شد، زیرا پایپها خوانده نمیشوند.تغییر یافته در نسخهی 3.3: timeout افزوده شد.
تغییر یافته در نسخهی 3.12: ترتیب جستجوی پوستهی ویندوز برای
shell=Trueتغییر کرد. پوشهی جاری و%PATH%با%COMSPEC%و%SystemRoot%\System32\cmd.exeجایگزین شدهاند. در نتیجه، قرار دادن یک برنامهی مخرب با نامcmd.exeدر پوشهی جاری دیگر کار نمیکند.
- subprocess.check_call(args, *, stdin=None, stdout=None, stderr=None, shell=False, cwd=None, timeout=None, **other_popen_kwargs)¶
فرمان را با آرگومانها اجرا میکند. منتظر میماند تا فرمان کامل شود. اگر کد بازگشت صفر بود، بازمیگردد؛ در غیر این صورت
CalledProcessErrorرا پرتاب میکند. شیءCalledProcessErrorکد بازگشت را در ویژگیreturncodeخواهد داشت. اگرcheck_call()نتوانست فرایند را آغاز کند، استثنای پرتابشده را منتشر میکند.کدی که نیاز به گرفتن stdout یا stderr دارد، باید بهجای آن از
run()استفاده کند:run(..., check=True)
برای سرکوب stdout یا stderr، مقدار
DEVNULLرا ارائه دهید.آرگومانهای نشاندادهشده در بالا تنها چند مورد رایج هستند. امضای کامل تابع همانند امضای سازندهی
Popenاست؛ این تابع تمام آرگومانهای ارائهشده بهجز timeout را مستقیماً به آن رابط منتقل میکند.توجه
از
stdout=PIPEیاstderr=PIPEبا این تابع استفاده نکنید. اگر فرایند فرزند به اندازهای خروجی به یک پایپ تولید کند که بافر پایپ سیستمعامل (OS pipe buffer) را پر کند، مسدود خواهد شد، زیرا پایپها خوانده نمیشوند.تغییر یافته در نسخهی 3.3: timeout افزوده شد.
تغییر یافته در نسخهی 3.12: ترتیب جستجوی پوستهی ویندوز برای
shell=Trueتغییر کرد. پوشهی جاری و%PATH%با%COMSPEC%و%SystemRoot%\System32\cmd.exeجایگزین شدهاند. در نتیجه، قرار دادن یک برنامهی مخرب با نامcmd.exeدر پوشهی جاری دیگر کار نمیکند.
- subprocess.check_output(args, *, stdin=None, stderr=None, shell=False, cwd=None, encoding=None, errors=None, universal_newlines=None, timeout=None, text=None, **other_popen_kwargs)¶
فرمان را با آرگومانها اجرا میکند و خروجی آن را برمیگرداند.
اگر کد بازگشتی غیرصفر باشد، یک
CalledProcessErrorپرتاب میشود. شیءCalledProcessErrorکد بازگشتی را در ویژگیreturncodeو هرگونه خروجی را در ویژگیoutputخواهد داشت.این معادل است با:
run(..., check=True, stdout=PIPE).stdout
آرگومانهای نشاندادهشده در بالا تنها برخی از آرگومانهای رایج هستند. امضای کامل تابع تا حد زیادی مشابه
run()است - بیشتر آرگومانها مستقیماً به آن رابط منتقل میشوند. یک تفاوت API نسبت به رفتارrun()وجود دارد: ارسالinput=Noneمانندinput=b''(یاinput=''، بسته به آرگومانهای دیگر) رفتار میکند، بهجای اینکه از دسته پرونده ورودی استاندارد والد استفاده کند.بهطور پیشفرض، این تابع داده را بهصورت بایتهای کدگذاریشده برمیگرداند. کدگذاری واقعی داده خروجی ممکن است به فرمان فراخوانیشده بستگی داشته باشد، بنابراین کدگشایی به متن اغلب باید در سطح کاربرد مدیریت شود.
این رفتار را میتوان با تنظیم text، encoding، errors یا universal_newlines روی
True، همانطور که در آرگومانهای پرکاربرد وrun()توضیح داده شده است، تغییر داد.برای اینکه خطای استاندارد نیز در نتیجه گرفته شود، از
stderr=subprocess.STDOUTاستفاده کنید:>>> subprocess.check_output( ... "ls non_existent_file; exit 0", ... stderr=subprocess.STDOUT, ... shell=True) 'ls: non_existent_file: No such file or directory\n'
اضافه شده در نسخهی 3.1.
تغییر یافته در نسخهی 3.3: timeout افزوده شد.
تغییر یافته در نسخهی 3.4: پشتیبانی از آرگومان کلیدواژهای input افزوده شد.
تغییر یافته در نسخهی 3.6: encoding و errors افزوده شدند. برای جزئیات،
run()را ببینید.اضافه شده در نسخهی 3.7: text بهعنوان نام مستعاری خواناتر برای universal_newlines افزوده شد.
تغییر یافته در نسخهی 3.12: ترتیب جستجوی پوستهی ویندوز برای
shell=Trueتغییر کرد. پوشهی جاری و%PATH%با%COMSPEC%و%SystemRoot%\System32\cmd.exeجایگزین شدهاند. در نتیجه، قرار دادن یک برنامهی مخرب با نامcmd.exeدر پوشهی جاری دیگر کار نمیکند.
جایگزینی توابع قدیمی با ماژول subprocess¶
در این بخش، «a به b تبدیل میشود» به این معناست که b میتواند بهعنوان جایگزینی برای a استفاده شود.
توجه
تمام توابع «a» در این بخش در صورتی که برنامهی اجراشده یافت نشود، (کموبیش) بهصورت خاموش شکست میخورند؛ جایگزینهای «b» در عوض OSError را پرتاب میکنند.
علاوه بر این، جایگزینهایی که از check_output() استفاده میکنند، اگر عملیات درخواستی کد بازگشت غیرصفری تولید کند، با CalledProcessError شکست خواهند خورد. خروجی همچنان بهعنوان ویژگی output استثنای پرتابشده در دسترس است.
در مثالهای زیر، فرض میکنیم که توابع مربوطه پیشتر از ماژول subprocess ایمپورت شدهاند.
جایگزین کردن جایگزینی دستور پوسته /bin/sh¶
output=$(mycmd myarg)
بهصورت زیر درمیآید:
output = check_output(["mycmd", "myarg"])
جایگزینی خط پایپ پوسته¶
output=$(dmesg | grep hda)
بهصورت زیر درمیآید:
p1 = Popen(["dmesg"], stdout=PIPE)
p2 = Popen(["grep", "hda"], stdin=p1.stdout, stdout=PIPE)
p1.stdout.close() # Allow p1 to receive a SIGPIPE if p2 exits.
output = p2.communicate()[0]
فراخوانی p1.stdout.close() پس از شروع p2 مهم است تا در صورتی که p2 پیش از p1 خارج شود، p1 یک SIGPIPE دریافت کند.
بهعنوان جایگزین، برای ورودی قابلاعتماد، پشتیبانی خط پایپ خود پوسته همچنان میتواند بهصورت مستقیم استفاده شود:
output=$(dmesg | grep hda)
بهصورت زیر درمیآید:
output = check_output("dmesg | grep hda", shell=True)
جایگزینی os.system()¶
sts = os.system("mycmd" + " myarg")
# becomes
retcode = call("mycmd" + " myarg", shell=True)
یادداشتها:
معمولاً نیازی به فراخوانی برنامه از طریق پوسته نیست.
مقدار بازگشتی
call()به شکل متفاوتی نسبت به مقدار بازگشتیos.system()کدگذاری میشود.تابع
os.system()در حین اجرای دستور، سیگنالهای SIGINT و SIGQUIT را نادیده میگیرد، اما فراخواننده باید هنگام استفاده از ماژولsubprocessاین کار را بهطور جداگانه انجام دهد.
یک مثال واقعیتر به این شکل خواهد بود:
try:
retcode = call("mycmd" + " myarg", shell=True)
if retcode < 0:
print("Child was terminated by signal", -retcode, file=sys.stderr)
else:
print("Child returned", retcode, file=sys.stderr)
except OSError as e:
print("Execution failed:", e, file=sys.stderr)
جایگزینی خانوادهی os.spawn¶
مثال P_NOWAIT:
pid = os.spawnlp(os.P_NOWAIT, "/bin/mycmd", "mycmd", "myarg")
==>
pid = Popen(["/bin/mycmd", "myarg"]).pid
مثال P_WAIT:
retcode = os.spawnlp(os.P_WAIT, "/bin/mycmd", "mycmd", "myarg")
==>
retcode = call(["/bin/mycmd", "myarg"])
مثال بردار:
os.spawnvp(os.P_NOWAIT, path, args)
==>
Popen([path] + args[1:])
مثال محیط:
os.spawnlpe(os.P_NOWAIT, "/bin/mycmd", "mycmd", "myarg", env)
==>
Popen(["/bin/mycmd", "myarg"], env={"PATH": "/usr/bin"})
جایگزینی os.popen()¶
مدیریت کد بازگشت بهصورت زیر ترجمه میشود:
pipe = os.popen(cmd, 'w')
...
rc = pipe.close()
if rc is not None and rc >> 8:
print("There were some errors")
==>
process = Popen(cmd, stdin=PIPE)
...
process.stdin.close()
if process.wait() != 0:
print("There were some errors")
توابع فراخوانی پوستهی قدیمی¶
این ماژول همچنین توابع قدیمی زیر را از ماژول commands در نسخههای 2.x ارائه میدهد. این عملیاتها بهطور ضمنی پوستهی سیستم را فراخوانی میکنند و هیچکدام از تضمینهای توصیفشده در بالا در مورد امنیت و سازگاری مدیریت استثنا برای این توابع معتبر نیستند.
- subprocess.getstatusoutput(cmd, *, encoding=None, errors=None)¶
(exitcode, output)حاصل از اجرای cmd در یک پوسته را برمیگرداند.رشتهی cmd را در پوسته با
check_output()اجرا میکند و یک تاپل دوتایی(exitcode, output)برمیگرداند. encoding و errors برای کدگشایی خروجی استفاده میشوند؛ برای جزئیات بیشتر، یادداشتهای مربوط به آرگومانهای پرکاربرد را ببینید.یک خط جدید انتهایی از خروجی حذف میشود. کد خروجی فرمان را میتوان بهعنوان کد بازگشتی subprocess تفسیر کرد. مثال:
>>> subprocess.getstatusoutput('ls /bin/ls') (0, '/bin/ls') >>> subprocess.getstatusoutput('cat /bin/junk') (1, 'cat: /bin/junk: No such file or directory') >>> subprocess.getstatusoutput('/bin/junk') (127, 'sh: /bin/junk: not found') >>> subprocess.getstatusoutput('/bin/kill $$') (-15, '')
دسترسپذیری: Unix, Windows.
تغییر یافته در نسخهی 3.3.4: پشتیبانی از ویندوز اضافه شد.
این تابع اکنون به جای (status, output) که در پایتون 3.3.3 و نسخههای پیشتر برمیگرداند، (exitcode, output) را برمیگرداند. exitcode همان مقدار
returncodeرا دارد.تغییر یافته در نسخهی 3.11: پارامترهای encoding و errors افزوده شدند.
- subprocess.getoutput(cmd, *, encoding=None, errors=None)¶
خروجی (stdout و stderr) اجرای cmd در یک پوسته را برمیگرداند.
مانند
getstatusoutput()، با این تفاوت که کد خروجی نادیده گرفته میشود و مقدار بازگشتی، رشتهای حاوی خروجی فرمان است. مثال:>>> subprocess.getoutput('ls /bin/ls') '/bin/ls'
دسترسپذیری: Unix, Windows.
تغییر یافته در نسخهی 3.3.4: پشتیبانی از ویندوز اضافه شد
تغییر یافته در نسخهی 3.11: پارامترهای encoding و errors افزوده شدند.
یادداشتها¶
رفتار مهلت¶
هنگام استفاده از پارامتر timeout در توابعی مانند run()، Popen.wait() یا Popen.communicate()، کاربران باید از رفتارهای زیر آگاه باشند:
تأخیر در ایجاد فرایند: خودِ ایجاد اولیه فرایند در بسیاری از APIهای پلتفرم نمیتواند قطع شود. این بدان معناست که حتی هنگام تعیین مهلت زمانی، تضمین نمیشود که استثنای مهلت زمانی را دستکم تا پس از پایان ایجاد فرایند، هر چقدر هم که طول بکشد، مشاهده کنید.
مقادیر بسیار کوچک مهلت زمانی: تنظیم مقادیر بسیار کوچک مهلت زمانی (مانند چند میلیثانیه) ممکن است تقریباً بلافاصله منجر به استثناهای
TimeoutExpiredشود، زیرا ایجاد فرآیند و زمانبندی سیستم ذاتاً به زمان نیاز دارند.
تبدیل دنبالهای از آرگومانها به رشته در ویندوز¶
در ویندوز، دنبالهی args به رشتهای تبدیل میشود که میتوان آن را با استفاده از قوانین زیر تجزیه کرد (که این قوانین با قوانین مورد استفاده در رانتایم C مایکروسافت مطابقت دارند):
آرگومانها با فضای سفید جدا میشوند، که یا فاصله است یا تب.
یک رشته که با علامتهای نقلقول دوتایی احاطه شده باشد، بهعنوان یک آرگومان واحد تفسیر میشود، صرفنظر از فضای خالی موجود در آن. میتوان یک رشته داخل علامت نقلقول را در یک آرگومان تعبیه کرد.
علامت نقلقول دوتایی که پیش از آن یک بکاسلش آمده باشد، بهعنوان علامت نقلقول دوتایی لفظی تفسیر میشود.
بکاسلشها بهصورت لفظی تفسیر میشوند، مگر اینکه بلافاصله پیش از یک علامت نقلقول دوتایی قرار بگیرند.
اگر بکاسلشها بلافاصله پیش از یک علامت نقلقول دوتایی بیایند، هر جفت از بکاسلشها بهعنوان یک بکاسلش واقعی تفسیر میشود. اگر تعداد بکاسلشها فرد باشد، آخرین بکاسلش، علامت نقلقول دوتایی بعدی را همانطور که در قاعدهی ۳ توضیح داده شده است، خنثی میکند.
همچنین ملاحظه نمائید
shlexماژولی که تابعی برای تجزیه و خنثیسازی سطرهای فرمان ارائه میکند.
غیرفعالسازی استفاده از posix_spawn()¶
در لینوکس، subprocess بهطور پیشفرض هر زمان که این کار امن باشد، بهجای fork() بهصورت داخلی از فراخوانی سیستمی vfork() استفاده میکند. این کار عملکرد را بهطور قابلتوجهی بهبود میبخشد.
subprocess._USE_POSIX_SPAWN = False # See CPython issue gh-NNNNNN.
تنظیم این مورد روی false در هر نسخهای از پایتون بیخطر است. این کار در نسخههای قدیمیتر یا جدیدتری که از آن پشتیبانی نمیشود، هیچ تأثیری نخواهد داشت. فرض نکنید این ویژگی برای خواندن در دسترس است. با وجود این نام، مقدار true نشان نمیدهد که تابع مربوطه استفاده خواهد شد، بلکه تنها نشان میدهد که ممکن است استفاده شود.
لطفاً هر زمان که مجبور شدید از این گزینههای خصوصی (private knobs) استفاده کنید، مسئلههایی (issues) را همراه با روشی برای بازتولید مشکلی که مشاهده میکردید ثبت کنید. از یک کامنت (comment) در کد خود به آن مسئله پیوند دهید.
اضافه شده در نسخهی 3.8: _USE_POSIX_SPAWN