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

سرور مجازی NVMe

اجرای دستورات شل با پایتون

0 78
زمان لازم برای مطالعه: 6 دقیقه


معرفی

کارهای تکراری برای اتوماسیون آماده هستند. برای توسعه دهندگان و مدیران سیستم معمول است که کارهای معمول مانند بررسی سلامت و پشتیبان گیری از فایل ها را با اسکریپت های پوسته خودکار کنند. با این حال، با پیچیده تر شدن این وظایف، نگهداری اسکریپت های پوسته ممکن است سخت تر شود.

خوشبختانه، ما می توانیم به جای اسکریپت های پوسته برای اتوماسیون از پایتون استفاده کنیم. پایتون روش‌هایی را برای اجرای دستورات پوسته ارائه می‌کند، و با پشتیبانی اضافی از اکوسیستم پایتون، عملکردی مشابه اسکریپت‌های پوسته را به ما می‌دهد. یادگیری روش اجرای دستورات پوسته در پایتون دری را برای ما باز می کند تا وظایف رایانه را به روشی ساختاریافته و مقیاس پذیر به طور خودکار انجام دهیم.

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

استفاده از 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

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

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

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