وبلاگ رسانگار
با ما حرفه ای باشید

سرور مجازی NVMe

سیستم عامل پایتون و دستورات فرعی Popen

0 11
زمان لازم برای مطالعه: 2 دقیقه


معرفی

پایتون چندین گزینه برای اجرای فرآیندهای خارجی و تعامل با سیستم عامل ارائه می دهد. با این حال، روش ها برای پایتون 2 و 3 متفاوت است. پایتون 2 چندین متد در آن دارد os ماژول، که در حال حاضر منسوخ شده و جایگزین شده است subprocess ماژول، که گزینه ترجیحی در پایتون 3 است.

در طول این مقاله در مورد انواع مختلف صحبت خواهیم کرد os و subprocess روش ها، روش استفاده از آنها، تفاوت آنها با یکدیگر، روی از چه نسخه ای از پایتون باید استفاده کرد و حتی چگونه دستورات قدیمی را به دستورات جدیدتر تبدیل کرد.

امیدواریم تا پایان این مقاله درک بهتری از روش فراخوانی دستورات خارجی از کد پایتون و روشی که باید برای انجام آن استفاده کنید، داشته باشید.

اولش بزرگتره os.popen* مواد و روش ها.

روش های os.popen*

این os ماژول چهار روش مختلف را ارائه می دهد که به ما امکان می دهد با سیستم عامل تعامل داشته باشیم (درست مانند خط فرمان) و ایجاد یک لوله به دستورات دیگر این روش هایی که من به آنها اشاره می کنم عبارتند از: popen، popen2، popen3، و popen4، که همه آنها در بخش های بعدی توضیح داده شده است.

هدف هر یک از این روش ها این است که بتوانید برنامه های دیگر را از کد پایتون خود فراخوانی کنید. این می تواند یک فایل اجرایی دیگر را فراخوانی کند، مانند برنامه C++ کامپایل شده خودتان، یا یک دستور پوسته مانند ls یا mkdir.

os.popen

این os.popen متد یک لوله را از یک دستور باز می کند. این لوله به فرمان اجازه می دهد تا خروجی خود را به دستور دیگری ارسال کند. خروجی یک فایل باز است که توسط برنامه های دیگر قابل دسترسی است.

نحو به شرح زیر است:

os.popen(command(, mode(, bufsize)))

اینجا command پارامتر چیزی است که شما اجرا می کنید و خروجی آن از طریق یک فایل باز در دسترس خواهد بود. بحث و جدل mode مشخص می کند که آیا این فایل خروجی قابل خواندن (‘r’) یا قابل نوشتن (‘w’) است یا خیر. الحاق یک ‘b’ به mode فایل را در حالت باینری باز می کند. بنابراین، برای مثال “rb” یک شی فایل باینری قابل خواندن تولید می کند.

برای بازیابی کد خروجی دستور اجرا شده، باید از close() روش شی فایل

این bufsize پارامتر می گوید popen چه مقدار داده باید بافر شود و می تواند یکی از مقادیر زیر را در نظر بگیرد:

  • 0 = بافر نشده (مقدار پیش فرض)
  • 1 = خط بافر شده است
  • N = اندازه تقریبی بافر، زمانی که N > 0; و مقدار پیش فرض، زمانی که N <0 باشد

این روش برای پلتفرم های یونیکس و ویندوز موجود است و از نسخه 2.6 پایتون منسوخ شده است. اگر در حال حاضر از این روش استفاده می کنید و می خواهید به نسخه Python 3 سوئیچ کنید، در اینجا معادل آن است. subprocess نسخه برای پایتون 3:

روش جایگزین توسط
pipe = os.popen(‘cmd’, ‘r’, bufsize) pipe = Popen(‘cmd’, shell=True, bufsize=bufsize, stdout=PIPE).stdout
pipe = os.popen(‘cmd’, ‘w’, bufsize) pipe = Popen(‘cmd’, shell=True, bufsize=bufsize, stdin=PIPE).stdin

کد زیر نمونه ای از روش استفاده از آن را نشان می دهد os.popen روش:

import os

p = os.popen('ls -la')
print(p.read())

کد بالا از سیستم عامل می خواهد که همه فایل ها را در فهرست فعلی فهرست کند. خروجی روش ما که در آن ذخیره می شود p، یک فایل باز است که در خط آخر کد خوانده و چاپ می شود. نتیجه این کد (در زمینه فهرست فعلی من) به شرح زیر است:

$ python popen_test.py 
total 32
drwxr-xr-x   7 scott  staff  238 Nov  9 09:13 .
drwxr-xr-x  29 scott  staff  986 Nov  9 09:08 ..
-rw-r--r--   1 scott  staff   52 Nov  9 09:13 popen2_test.py
-rw-r--r--   1 scott  staff   55 Nov  9 09:14 popen3_test.py
-rw-r--r--   1 scott  staff   53 Nov  9 09:14 popen4_test.py
-rw-r--r--   1 scott  staff   49 Nov  9 09:13 popen_test.py
-rw-r--r--   1 scott  staff    0 Nov  9 09:13 subprocess_popen_test.py

os.popen2

این روش بسیار شبیه به روش قبلی است. تفاوت اصلی در خروجی روش است. در این مورد دو شی فایل را برمی گرداند، یکی برای stdin و یک فایل دیگر برای stdout.

نحو به شرح زیر است:

popen2(cmd(, mode(, bufsize)))

این آرگومان ها همان معنای روش قبلی را دارند. os.popen.

این popen2 روش برای هر دو سیستم عامل یونیکس و ویندوز در دسترس است. با این حال، فقط در پایتون 2 یافت می شود. باز هم اگر می خواهید از آن استفاده کنید subprocess نسخه به جای آن (با جزئیات بیشتر در زیر نشان داده شده است)، به جای آن از موارد زیر استفاده کنید:

روش جایگزین توسط
(child_stdin، child_stdout) = os.popen2(‘cmd’، حالت، bufsize)

p = Popen(‘cmd’، shell=True، bufsize=bufsize، stdin=PIPE، stdout=PIPE، close_fds=True)
(child_stdin, child_stdout) = (p.stdin, p.stdout)

کد زیر یک مثال را نشان می دهد روی روش استفاده از این روش:

import os

in, out = os.popen2('ls -la')
print(out.read())

این کد همان نتایجی را ایجاد می کند که در خروجی کد اول در بالا نشان داده شده است. تفاوت در اینجا این است که خروجی از popen2 متد از دو فایل تشکیل شده است. بنابراین، خط دوم کد دو متغیر را تعریف می کند: in و out. در سطر آخر فایل خروجی را می خوانیم out و print آن را به console.

os.popen3

این روش بسیار شبیه به روش های قبلی است. با این حال، تفاوت این است که خروجی دستور مجموعه ای از سه فایل است: stdin، stdout و stderr.

نحو عبارت است از:

os.popen3(cmd(, mode(, bufsize)))

جایی که استدلال ها cmd، mode، و bufsize همان مشخصات روش های قبلی را دارند. این روش برای پلتفرم های یونیکس و ویندوز در دسترس است.

توجه داشته باشید که این روش منسوخ شده است و مستندات پایتون به ما توصیه می کند که آن را جایگزین کنیم popen3 روش به شرح زیر است:

روش جایگزین توسط

(child_stdin,
child_stdout,
child_stderr) = os.popen3(‘cmd’، حالت، bufsize)

p = Popen(‘cmd’, shell=True, bufsize=bufsize,
stdin=PIPE، stdout=PIPE، stderr=PIPE، close_fds=True)
(child_stdin,
child_stdout,
child_stderr) = (p.stdin، p.stdout، p.stderr)

همانطور که در مثال های قبلی، کد زیر همان نتیجه ای را که در مثال اول ما مشاهده شد، ایجاد می کند.

import os

in, out, err = os.popen3('ls -la')
print(out.read())

اما در این حالت باید سه فایل stdin، stdout و stderr را تعریف کنیم. لیست فایل های ما ls -la دستور در ذخیره می شود out فایل.

os.popen4

همانطور که احتمالا حدس زدید، os.popen4 روش مشابه روش های قبلی است. با این حال، در این مورد، تنها دو فایل را برمی گرداند، یکی برای stdin و دیگری برای stdout و stderr.

این روش برای پلتفرم های یونیکس و ویندوز موجود است و (تعجب!) نیز از نسخه 2.6 منسوخ شده است. برای جایگزینی آن با متن مربوطه subprocess Popen تماس بگیرید، موارد زیر را انجام دهید:

روش جایگزین توسط

(child_stdin، child_stdout_and_stderr) = os.popen4(‘cmd’، حالت، bufsize)

p = Popen(‘cmd’, shell=True, bufsize=bufsize,
stdin=PIPE، stdout=PIPE، stderr=STDOUT، close_fds=True)
(child_stdin, child_stdout_and_stderr) = (p.stdin, p.stdout)

کد زیر همان نتیجه را در مثال های قبلی ایجاد می کند که در خروجی کد اول در بالا نشان داده شده است.

import os

in, out = os.popen4('ls -la')
print(we.read())

همانطور که از کد بالا می بینیم، روش بسیار شبیه به آن است popen2. با این حال out فایل موجود در برنامه نتایج ترکیبی هر دو جریان stdout و stderr را نشان می دهد.

خلاصه تفاوت ها

تفاوت های بین متفاوت popen* دستورات همگی مربوط به خروجی خود هستند که در جدول زیر خلاصه شده است:

روش استدلال ها
ظاهر شود stdout
popen2 stdin، stdout
popen3 stdin، stdout، stderr
popen4 stdin، stdout و stderr

علاوه بر این popen2، popen3، و popen4 فقط در پایتون 2 در دسترس هستند اما در پایتون 3 موجود نیستند. پایتون 3 این موارد را در دسترس دارد popen روش، اما توصیه می شود از subprocess ماژول به جای آن، که در بخش بعدی با جزئیات بیشتر توضیح خواهیم داد.

susbprocess. روش Popen

این ماژول زیر فرآیند با هدف جایگزینی چندین روش موجود در ایجاد شده است os ماژول، که چندان کارآمد در نظر گرفته نمی شد. در این ماژول، ما جدید را پیدا می کنیم Popen کلاس

اسناد پایتون استفاده از Popen در موارد پیشرفته، زمانی که روش های دیگر مانند subprocess.call نمی تواند نیازهای ما را برآورده کند. این روش امکان اجرای یک برنامه را در کودکی فراهم می کند process. زیرا این توسط سیستم عامل به صورت جداگانه اجرا می شود process، نتایج به پلت فرم وابسته است.

پارامترهای موجود به شرح زیر است:

subprocess.Popen(args, bufsize=0, executable=None, stdin=None, stdout=None, stderr=None, preexec_fn=None, close_fds=False, shell=False, cwd=None, env=None, universal_newlines=False, startupinfo=None, creationflags=0)

یک تفاوت اصلی از Popen این است که یک کلاس است و نه فقط یک متد. بنابراین، هنگامی که ما تماس بگیرید subprocess.Popen، ما در واقع سازنده کلاس را فراخوانی می کنیم Popen.

چندین آرگومان در سازنده وجود دارد. مهمترین چیز برای درک این است args، که حاوی دستور برای process می خواهیم اجرا کنیم می توان آن را به عنوان دنباله ای از پارامترها (از طریق یک آرایه) یا به عنوان یک رشته فرمان منفرد مشخص کرد.

دومین استدلالی که درک آن مهم است این است shell، که به صورت پیش فرض است False. در یونیکس، زمانی که باید دستوری را اجرا کنیم که متعلق به پوسته است، مانند ls -la، باید تنظیم کنیم shell=True.

به عنوان مثال، کد زیر دستور یونیکس را فراخوانی می کند ls -la از طریق یک پوسته

import subprocess
subprocess.Popen('ls -la', shell=True)

نتایج را می توان در خروجی زیر مشاهده کرد:

$ python subprocess_popen_test.py 
total 40
drwxr-xr-x   7 scott  staff  238 Nov  9 09:13 .
drwxr-xr-x  29 scott  staff  986 Nov  9 09:08 ..
-rw-r--r--   1 scott  staff   52 Nov  9 09:13 popen2_test.py
-rw-r--r--   1 scott  staff   55 Nov  9 09:14 popen3_test.py
-rw-r--r--   1 scott  staff   53 Nov  9 09:14 popen4_test.py
-rw-r--r--   1 scott  staff   49 Nov  9 09:13 popen_test.py
-rw-r--r--   1 scott  staff   56 Nov  9 09:16 subprocess_popen_test.py

با استفاده از مثال زیر از یک ماشین ویندوز، می‌توانیم تفاوت‌های استفاده از آن را ببینیم shell پارامتر راحت تر در اینجا ما Microsoft Excel را از پوسته یا به عنوان یک برنامه اجرایی باز می کنیم. از پوسته، درست مثل این است که اکسل را از یک پنجره فرمان باز کنیم.

کد زیر اکسل را از پوسته باز می کند (توجه داشته باشید که باید مشخص کنیم shell=True):

import subprocess
subprocess.Popen("start excel", shell=True)

با این حال، می‌توانیم با فراخوانی فایل اجرایی اکسل، همان نتایج را دریافت کنیم. در این مورد، ما از پوسته استفاده نمی کنیم، بنابراین آن را با مقدار پیش فرض آن (False) اما باید مسیر کامل فایل اجرایی را مشخص کنیم.

import subprocess
subprocess.Popen("C:\Program Files (x86)\Microsoft Office\Office15\excel.exe")

علاوه بر این، هنگامی که ما نمونه Popen کلاس، ما به چندین روش مفید دسترسی داریم:

روش شرح
Popen.poll() بررسی می کند که آیا کودک process خاتمه یافته است.
Popen.wait() منتظر بچه باش process خاتمه دادن
Popen.communicate() اجازه می دهد تا با process.
Popen.send_signal() به کودک سیگنال می فرستد process.
Popen.terminate() کودک را متوقف می کند process.
Popen.kill() کودکی را می کشد process.

لیست کامل را می توان در اسناد فرعی. متداول ترین روش مورد استفاده در اینجا است communicate.

این communicate متد به ما امکان می دهد داده ها را از ورودی استاندارد بخوانیم و همچنین به ما امکان می دهد داده ها را به خروجی استاندارد ارسال کنیم. یک تاپل تعریف شده را برمی گرداند (stdoutdata, stderrdata).

به عنوان مثال، کد زیر ویندوز را ترکیب می کند dir و sort دستورات

import subprocess

p1 = subprocess.Popen('dir', shell=True, stdin=None, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
p2 = subprocess.Popen('sort /R', shell=True, stdin=p1.stdout)

p1.stdout.close()
out, err = p2.communicate() 

به منظور ترکیب هر دو دستور، ما دو فرآیند فرعی ایجاد می کنیم، یکی برای dir فرمان و دیگری برای sort فرمان از آنجایی که می خواهیم به ترتیب معکوس مرتب کنیم، اضافه می کنیم /R گزینه به sort زنگ زدن.

stdout را تعریف می کنیم process 1 به عنوان PIPE، که به ما امکان می دهد از خروجی استفاده کنیم process 1 به عنوان ورودی برای process 2. سپس باید stdout of را ببندیم process 1، بنابراین می توان از آن به عنوان ورودی استفاده کرد process 2. ارتباط بین process از طریق به دست می آید communicate روش.

اجرای این مورد از پوسته فرمان ویندوز موارد زیر را ایجاد می کند:

> python subprocess_pipe_test.py
11/09/2017  08:52 PM                  234 subprocess_pipe_test.py
11/09/2017  07:13 PM                   99 subprocess_pipe_test2.py
11/09/2017  07:08 PM                   66 subprocess_pipe_test3.py
11/09/2017  07:01 PM                   56 subprocess_pipe_test4.py
11/09/2017  06:48 PM     <DIR>            ..
11/09/2017  06:48 PM     <DIR>            .
 Volume Serial Number is 2E4E-56A3
 Volume in drive D is ECA
 Directory of D:\MyPopen
               4 File(s)            455 bytes
               2 Dir(s)  18,634,326,016 bytes free

بسته شدن

این os روش ها در گذشته گزینه خوبی بودند، اما در حال حاضر subprocess ماژول چندین روش دارد که استفاده از آنها قدرتمندتر و کارآمدتر است. از جمله ابزارهای موجود است Popen کلاس، که می تواند در موارد پیچیده تر استفاده شود. این کلاس همچنین شامل communicate روشی که به ما کمک می‌کند تا دستورات مختلف را برای عملکرد پیچیده‌تر کنار هم قرار دهیم.

از چی استفاده میکنی popen* روش ها برای، و شما کدام را ترجیح می دهید؟ در نظرات به ما اطلاع دهید!

(برچسب‌ها به ترجمه)# python



منتشر شده در 1403-01-29 04:55:04

امتیاز شما به این مطلب
دیدگاه شما در خصوص مطلب چیست ؟

آدرس ایمیل شما منتشر نخواهد شد.

لطفا دیدگاه خود را با احترام به دیدگاه های دیگران و با توجه به محتوای مطلب درج کنید