از طریق منوی جستجو مطلب مورد نظر خود در وبلاگ را به سرعت پیدا کنید
اجرای دستورات شل با پایتون
سرفصلهای مطلب
معرفی
کارهای تکراری برای اتوماسیون آماده هستند. برای توسعه دهندگان و مدیران سیستم معمول است که کارهای معمول مانند بررسی سلامت و پشتیبان گیری از فایل ها را با اسکریپت های پوسته خودکار کنند. با این حال، با پیچیده تر شدن این وظایف، نگهداری اسکریپت های پوسته ممکن است سخت تر شود.
خوشبختانه، ما می توانیم به جای اسکریپت های پوسته برای اتوماسیون از پایتون استفاده کنیم. پایتون روشهایی را برای اجرای دستورات پوسته ارائه میکند، و با پشتیبانی اضافی از اکوسیستم پایتون، عملکردی مشابه اسکریپتهای پوسته را به ما میدهد. یادگیری روش اجرای دستورات پوسته در پایتون دری را برای ما باز می کند تا وظایف رایانه را به روشی ساختاریافته و مقیاس پذیر به طور خودکار انجام دهیم.
در این مقاله به روش های مختلف اجرای دستورات پوسته در پایتون و شرایط ایده آل برای استفاده از هر روش می پردازیم.
استفاده از os.system برای اجرای یک فرمان
پایتون به ما این امکان را می دهد که بلافاصله یک فرمان پوسته ای را که در یک رشته ذخیره می شود با استفاده از عبارت اجرا کنیم os.system()
تابع. بیایید با ایجاد یک فایل پایتون جدید به نام شروع کنیم echo_adelle.py
و موارد زیر را وارد کنید:
import os
os.system("echo Hello from the other side!")
اولین کاری که در فایل پایتون خود انجام می دهیم این است import را os
ماژول، که شامل system
تابعی که می تواند دستورات پوسته را اجرا کند. خط بعدی دقیقاً همین کار را انجام می دهد echo
دستور در پوسته ما از طریق پایتون.
در ترمینال خود، این فایل را با استفاده از دستور زیر اجرا کنید و باید خروجی مربوطه را ببینید:
$ python3 echo_adelle.py
Hello from the other side!
به عنوان echo
دستورات به ما چاپ می کند stdout
، os.system()
خروجی را نیز نمایش می دهد روی ما stdout
جریان در حالی که در آن قابل مشاهده نیست console، os.system()
دستور کد خروجی دستور shell را برمی گرداند. کد خروج 0 یعنی بدون مشکل اجرا شد و هر عدد دیگری به معنای خطا است. به این ترتیب، می توانید جریان دستورات خود را کنترل کنید، نتایج را بررسی کنید و یا دوباره امتحان کنید یا در صورت عدم موفقیت تماس، خطا را برگردانید:
import os
home_dir = os.system("cd ~")
print("`cd ~` ran with exit code %d" % home_dir)
unknown_dir = os.system("cd doesnotexist")
print("`cd doesnotexis` ran with exit code %d" % unknown_dir)
در این اسکریپت، دو متغیر ایجاد می کنیم که نتیجه اجرای دستوراتی را که دایرکتوری را به پوشه اصلی و به پوشه ای که وجود ندارد، ذخیره می کند. با اجرای این فایل، خواهیم دید:
$ python3 cd_return_codes.py
`cd ~` ran with exit code 0
sh: line 0: cd: doesnotexist: No such file or directory
`cd doesnotexist` ran with exit code 256
اولین دستور که دایرکتوری را به فهرست اصلی تغییر می دهد، با موفقیت اجرا می شود. از این رو، os.system()
کد خروجی آن صفر را که در آن ذخیره می شود، برمی گرداند home_dir
. از سوی دیگر، unknown_dir
کد خروج شکست خورده را ذخیره می کند bash دستور تغییر دایرکتوری به پوشه ای که وجود ندارد.
این os.system()
تابع یک فرمان را اجرا می کند، هر خروجی از دستور را در آن چاپ می کند consoleو کد خروجی دستور را برمی گرداند. اگر بخواهیم کنترل دقیق تری بر ورودی و خروجی یک فرمان پوسته در پایتون داشته باشیم، باید از subprocess
مدول.
اجرای یک فرمان با فرآیند فرعی
این ماژول زیر فرآیند روش پیشنهادی پایتون برای اجرای دستورات پوسته است. این به ما انعطافپذیری میدهد تا خروجی دستورات پوسته یا ورودیها و خروجیهای زنجیرهای دستورات مختلف را با هم سرکوب کنیم، در حالی که همچنان تجربهای مشابه برای os.system()
برای موارد استفاده اساسی
در یک فایل جدید به نام list_subprocess.py
، بیایید دستوری را با subprocess
مدول:
import subprocess
list_files = subprocess.run(("ls", "-l"))
print("The exit code was: %d" % list_files.returncode)
در خط اول، ما import را subprocess
ماژول، که بخشی از کتابخانه استاندارد پایتون است. سپس از subprocess.run()
تابع برای اجرای دستور. پسندیدن os.system()
، subprocess.run()
دستور کد خروجی آنچه اجرا شده را برمی گرداند.
بر خلاف os.system()
، توجه کنید که چگونه subprocess.run()
به جای یک رشته به لیستی از رشته ها به عنوان ورودی نیاز دارد. اولین مورد لیست نام دستور است. آیتم های باقی مانده از لیست پرچم ها و آرگومان های دستور هستند.
توجه داشته باشید: به عنوان یک قانون سرانگشتی، باید آرگومان ها را بر اساس جدا کنید روی فضا، برای مثال ls -alh
خواهد بود ("ls", "-alh")
، در حالی که ls -a -l -h
، خواهد بود ("ls", "-a", -"l", "-h")
. به عنوان مثال دیگر، echo hello world
خواهد بود ("echo", "hello", "world")
، در حالیکه echo "hello world"
یا echo hello\ world
خواهد بود ("echo", "hello world")
.
این فایل و فایل خود را اجرا کنید consoleخروجی ‘s مشابه خواهد بود:
$ python3 list_subprocess.py
total 80
-rw-r--r--@ 1 rasanegar staff 216 Dec 6 10:29 cd_return_codes.py
-rw-r--r--@ 1 rasanegar staff 56 Dec 6 10:11 echo_adelle.py
-rw-r--r--@ 1 rasanegar staff 116 Dec 6 11:20 list_subprocess.py
The exit code was: 0
حالا بیایید سعی کنیم از یکی از ویژگی های پیشرفته تر استفاده کنیم subprocess.run()
، یعنی نادیده گرفتن خروجی به stdout
. در همان list_subprocess.py
فایل، تغییر:
list_files = subprocess.run(("ls", "-l"))
به این:
list_files = subprocess.run(("ls", "-l"), stdout=subprocess.DEVNULL)
اکنون خروجی استاندارد دستور به ویژه ارسال می شود /dev/null
دستگاه، به این معنی که خروجی ظاهر نمی شود روی کنسول های ما فایل را در پوسته خود اجرا کنید تا خروجی زیر را ببینید:
$ python3 list_subprocess.py
The exit code was: 0
اگر بخواهیم ورودی یک دستور را ارائه دهیم چه می شود؟ این subprocess.run()
این را با خود تسهیل می کند input
بحث و جدل:
import subprocess
useless_cat_call = subprocess.run(("cat"),
stdout=subprocess.PIPE,
text=True,
input="Hello from the other side")
print(useless_cat_call.stdout)
ما استفاده می کنیم subprocess.run()
با چند دستور، اجازه دهید آنها را مرور کنیم:
stdout=subprocess.PIPE
به پایتون می گوید که خروجی دستور را به یک شی هدایت کند تا بعداً به صورت دستی خوانده شودtext=True
برمی گرداندstdout
وstderr
به عنوان رشته نوع بازگشتی پیش فرض بایت است.input="Hello from the other side"
به پایتون می گوید که رشته را به عنوان ورودی به رشته اضافه کندcat
فرمان
با اجرای این خروجی زیر تولید می شود:
Hello from the other side
ما همچنین می توانیم یک Exception
بدون بررسی دستی مقدار بازگشتی در یک فایل جدید، false_subprocess.py
، کد زیر را اضافه کنید:
import subprocess
failed_command = subprocess.run(("false"), check=True)
print("The exit code was: %d" % failed_command.returncode)
در ترمینال خود، این فایل را اجرا کنید. خطای زیر را خواهید دید:
$ python3 false_subprocess.py
Traceback (most recent call last):
File "false_subprocess.py", line 4, in <module>
failed_command = subprocess.run(("false"), check=True)
File "/usr/local/python/3.7.5/Frameworks/Python.framework/Versions/3.7/lib/python3.7/subprocess.py", line 512, in run
output=stdout, stderr=stderr)
subprocess.CalledProcessError: Command '('false')' returned non-zero exit status 1.
با استفاده از check=True
، به پایتون می گوییم در صورت بروز خطا، استثناء را مطرح کند. از آنجایی که ما با یک خطا مواجه شدیم، print
بیانیه روی خط پایانی اجرا نشد.
این subprocess.run()
عملکرد به ما انعطاف پذیری فوق العاده ای می دهد که os.system()
هنگام اجرای دستورات پوسته این کار را نمی کند. این تابع یک انتزاع ساده شده است subprocess.Popen
کلاس، که عملکردهای اضافی را ارائه می دهد که می توانیم بررسی کنیم.
اجرای یک فرمان با Popen
این subprocess.Popen
کلاس هنگام تعامل با پوسته، گزینه های بیشتری را در اختیار توسعه دهنده قرار می دهد. با این حال، ما باید در مورد بازیابی نتایج و خطاها صریح تر باشیم.
به صورت پیش فرض، subprocess.Popen
اگر اجرای دستور آن به پایان نرسیده باشد، پردازش برنامه پایتون را متوقف نمی کند. در یک فایل جدید به نام list_popen.py
، عبارت زیر را تایپ کنید:
import subprocess
list_dir = subprocess.Popen(("ls", "-l"))
list_dir.wait()
این کد معادل کد است list_subprocess.py
. با استفاده از دستوری اجرا می کند subprocess.Popen
و قبل از اجرای بقیه اسکریپت پایتون منتظر می ماند تا کامل شود.
فرض کنید نمیخواهیم منتظر بمانیم تا دستور شل ما اجرا شود تا برنامه بتواند کار کند روی چیز های دیگر. چگونه متوجه می شود که اجرای دستور shell به پایان رسیده است؟
این poll()
متد در صورتی که اجرای دستوری به پایان رسیده باشد، کد خروج را برمی گرداند None
اگر هنوز در حال اجراست به عنوان مثال، اگر می خواستیم بررسی کنیم که آیا list_dir
به جای منتظر ماندن کامل بود، خط کد زیر را خواهیم داشت:
list_dir.poll()
برای مدیریت ورودی و خروجی با subprocess.Popen
، باید از آن استفاده کنیم communicate()
روش.
در یک فایل جدید به نام cat_popen.py
، قطعه کد زیر را اضافه کنید:
import subprocess
useless_cat_call = subprocess.Popen(("cat"), stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE, text=True)
output, errors = useless_cat_call.communicate(input="Hello from the other side!")
useless_cat_call.wait()
print(output)
print(errors)
این communicate()
روش طول می کشد input
آرگومانی که برای ارسال ورودی به فرمان پوسته استفاده می شود. این communicate
متد نیز هر دو را برمی گرداند stdout
و stderr
وقتی تنظیم می شوند.
با دیدن ایده های اصلی پشت سر subprocess.Popen
، اکنون به سه روش برای اجرای دستورات پوسته در پایتون پرداخته ایم. بیایید ویژگی های آنها را دوباره بررسی کنیم تا بدانیم کدام روش برای نیازهای یک پروژه مناسب تر است.
بهترین روش برای اجرای دستورات شل با پایتون؟
اگر لازم است یک یا چند دستور ساده را اجرا کنید و اگر خروجی آنها به دستور برود مهم نیست console، می توانید استفاده کنید os.system()
فرمان اگر می خواهید ورودی و خروجی یک فرمان پوسته را مدیریت کنید، از آن استفاده کنید subprocess.run()
. اگر میخواهید دستوری را اجرا کنید و در حین اجرای آن به انجام کارهای دیگر ادامه دهید، از آن استفاده کنید subprocess.Popen
.
در اینجا جدولی با برخی از تفاوتهای کاربری وجود دارد که میتوانید برای اطلاع از تصمیم خود از آن استفاده کنید:
os.system | subprocess.run | زیر فرآیند.باز شود | |
---|---|---|---|
به آرگومان های تجزیه شده نیاز دارد | نه | آره | آره |
منتظر فرمان است | آره | آره | نه |
با stdin و stdout ارتباط برقرار می کند | نه | آره | آره |
برمی گرداند | ارزش بازگشتی | هدف – شی | هدف – شی |
نتیجه
پایتون به شما اجازه می دهد تا دستورات پوسته را اجرا کنید که می توانید از آنها برای راه اندازی برنامه های دیگر یا مدیریت بهتر اسکریپت های پوسته ای که برای اتوماسیون استفاده می کنید استفاده کنید. بسته به روی مورد استفاده ما، ما می توانیم استفاده کنیم os.system()
، subprocess.run()
یا subprocess.Popen
برای اجرا bash دستورات
با استفاده از این تکنیک ها، چه کار خارجی را از طریق پایتون اجرا می کنید؟
(برچسبها به ترجمه)# python
منتشر شده در 1403-01-01 22:49:03