یک برنامه فرزند را در یک فرایند جدید اجرا میکند. در 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 در WinAPI CreateProcess را ببینید، و توجه داشته باشید که هنگام تعیین یا جستوجوی مسیر اجرایی با 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 ندارید.
هنگام ایجاد اشیاء پرونده پایپ 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() در فرایند فرزند پیش از اجرای زیرفرایند انجام میشود.
تغییر یافته در نسخهی 3.2: start_new_session افزوده شد.
اگر process_group یک عدد صحیح غیرمنفی باشد، فراخوانی سیستمی setpgid(0, value) در فرایند فرزند پیش از اجرای زیرفرایند انجام خواهد شد.
تغییر یافته در نسخهی 3.11: process_group اضافه شد.
اگر group برابر None نباشد، فراخوانی سیستمی setregid() در فرایند فرزند پیش از اجرای زیرفرایند انجام خواهد شد. اگر مقدار ارائهشده یک رشته باشد، از طریق grp.getgrnam() جستجو خواهد شد و از مقدار موجود در gr_gid استفاده خواهد شد. اگر مقدار یک عدد صحیح باشد، عیناً ارسال خواهد شد. (فقط POSIX)
اگر extra_groups برابر None نباشد، فراخوانی سیستمی setgroups() پیش از اجرای زیرفرآیند در فرآیند فرزند انجام خواهد شد. رشتههای ارائهشده در extra_groups با استفاده از grp.getgrnam() جستجو خواهند شد و مقادیر موجود در gr_gid به کار خواهند رفت. مقادیر عدد صحیح عیناً ارسال خواهند شد. (فقط POSIX)
اگر user برابر None نباشد، فراخوانی سیستمی setreuid() در فرایند فرزند پیش از اجرای زیرفرایند انجام میشود. اگر مقدار ارائهشده یک رشته باشد، از طریق pwd.getpwnam() جستجو میشود و از مقدار pw_uid استفاده میشود. اگر مقدار یک عدد صحیح باشد، عیناً ارسال میشود. (فقط POSIX)
نکته
تعیین user، عضویتهای گروه تکمیلی موجود را حذف نمیکند! فراخواننده همچنین باید extra_groups=() را ارسال کند تا عضویت گروه فرایند فرزند را برای اهداف امنیتی کاهش دهد.
اگر umask منفی نباشد، فراخوانی سیستمی umask() پیش از اجرای زیرفرایند، در فرایند فرزند انجام میشود.
اگر 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 غیرصفر شکست میخورد.