اوامر لغة بايثون لنظام التشغيل من خلال مكتبة subprocess

اوامر لغة بايثون - بايثونات

اوامر لغة بايثون :

اوامر لغة بايثون لنظام التشغيل يُمكن تنفيذها بأكثر من طريقة. في بايثون، تعلمنا في درس “أُكتب برامج CLI بسعادة مع مكتبة Click في لغة البايثون” أن بإمكاننا جعل برامجنا أن تنفذ أوامر نظام التشغيل في نافذة سطر الأوامر وذلك من خلال استدعاء وظيفة  ()system من مكتبة os وتمرير الأمر المراد تنفيذه إليها.

[pastacode lang=”python” manual=”import%20os%0A%0A%23%20use%20dir%20on%20windows%0Amy_output%20%3D%20os.system(%22ls%20-al%22)%0A” message=”” highlight=”” provider=”manual”/]

لتكون النتيجة هي عرض الأدلة و الملفات الموجودة في الدليل الحالي:

[pastacode lang=”bash” manual=”Total%2056%0Adrwxr-xr-x%201%20runner%20runner%204096%20Jan%2022%2022%3A21.%0Adrwxr-xr-x%201%20root%20%20%20root%20%20%204096%20Sep%2021%2001%3A19%20..%0A-rw-r–r–%201%20runner%20runner%20%20220%20May%2015%20%202017%20.bash_logout%0A-rw-r–r–%201%20runner%20runner%203526%20May%2015%20%202017%20.bashrc%0Adrwxr-xr-x%201%20runner%20runner%204096%20Jan%2022%2022%3A20%20.cache%0Adrwxr-xr-x%201%20runner%20runner%204096%20Jan%2022%2022%3A11%20.config%0Adrwxr-xr-x%203%20runner%20runner%204096%20Sep%2021%2001%3A19%20.local%0A-rw-r–r–%201%20runner%20runner%20%20675%20May%2015%20%202017%20.profile%0Adrwxr-xr-x%202%20runner%20runner%204096%20Jan%2022%2022%3A21%20.upm%0A-rw-r–r–%201%20runner%20runner%20%20579%20Jan%2022%2022%3A11%20_test_runner.py%0A-rw-r–r–%201%20runner%20runner%20%20275%20Jan%2022%2022%3A21%20main.py%0A-rw-r–r–%201%20runner%20runner%20%20%2013%20Jan%2022%2022%3A11%20out.txt%0A” message=”” highlight=”” provider=”manual”/]

جميل، و لكن ماذا لو أردنا التحكم أكثر في مدخلات ومخرجات تلك العملية؟

لنفهم شيئا مهما في البداية وهو أن أي عملية يقوم بتنفيذها نظام التشغيل لا بد لها من مدخلات ومخرجات وأخطاء إن وجدت. حيث يُمكننا أن نُوجه المخرجات إلى ملف أو حتى لتكون مدخلات لعملية أخرى، بل و حتى التحكم بعرضها على شاشة سطر الأوامر، ولكن كيف يُمكن ذلك؟

اوامر لغة بايثون للنظام من خلال مكتبة subprocess

الجواب هو مكتبة subprocess  القياسية في بايثون والتي ستتيح لنا كل ذلك. لنستعرض أهم مميزاتها بشكل سريع و مفيد لكتابة برامج تتعامل مع مدخلات ومخرجات العمليات في نظام التشغيل.

[pastacode lang=”python” manual=”import%20subprocess%0A%0Aprocess_1%20%3D%20subprocess.run(‘ls’)” message=”” highlight=”” provider=”manual”/]

في الشيفرة السابقة، قمنا باستدعاء مكتبة subprocess وأنشأنا متغير باسم process_1 وفيه قمنا بتخزين مخرجات الوظيفة ()run والتي بدورها نفذت الأمر ls. وظيفة أمر ls في لينكس و ماك هي أن يعرض محتويات الدليل الحالي بشكل مختصر على شاشة سطر الأوامر. ملاحظة : يقوم نظام التشغيل باعتبار لوحة المفاتيح والفأرة كوسائل مدخلات قياسية والشاشة كوسيلة مخرجات قياسية.

عند طباعة محتويات المتغير أو الكائن process_1 من خلال أمر print ستكون المخرجات كالتالي:

[pastacode lang=”bash” manual=”CompletedProcess(args%3D’ls’%2C%20returncode%3D0)” message=”” highlight=”” provider=”manual”/]

نجد أن الكائن الناتج هو من نوع CompletedProcess  والمعامل المدخل هو النص ls والذي تم تنفيذه كأمر في سطر الأوامر والرمز المرجع للعملية صفر، أي أن العملية تمت من غير أخطاء.

ممتاز، ولكن ماذا لو أردنا ادخال الأمر السابق مع اختيارات إضافية لعرض تفاصيل عن محتويات الدليل الحالي كما في أمر “ls -al” ؟ جربوا الأمر وراقبوا ما سيحدث. سنجد أنه حدث خطأ ما و أوقف البرنامج نهائيا، فلماذا يحدث ذلك وما الحل؟

لدينا حلان الأول كالتالي:

[pastacode lang=”python” manual=”import%20subprocess%0A%0Aprocess_1%20%3D%20subprocess.run(‘ls%20-al’%2C%20shell%20%3DTrue)%0A%0Aprint(process_1)%0A” message=”” highlight=”” provider=”manual”/]

ما حدث هنا هو أننا قد حددنا قيمة للمعامل shell وهي True ومعنى ذلك أنه يتم تحويل النص في المعامل الأول كاملا إلي بايتات حقيقية ليتم تنفيذها على سطر الأوامر.

[pastacode lang=”bash” manual=”total%2056%0Adrwxr-xr-x%201%20runner%20runner%204096%20Jan%2023%2020%3A09%20.%0Adrwxr-xr-x%201%20root%20%20%20root%20%20%204096%20Sep%2021%2001%3A19%20..%0A-rw-r–r–%201%20runner%20runner%20%20220%20May%2015%20%202017%20.bash_logout%0A-rw-r–r–%201%20runner%20runner%203526%20May%2015%20%202017%20.bashrc%0Adrwxr-xr-x%204%20runner%20runner%204096%20Sep%2021%2001%3A20%20.cache%0Adrwxr-xr-x%201%20runner%20runner%204096%20Jan%2023%2020%3A00%20.config%0Adrwxr-xr-x%203%20runner%20runner%204096%20Sep%2021%2001%3A19%20.local%0A-rw-r–r–%201%20runner%20runner%20%20675%20May%2015%20%202017%20.profile%0Adrwxr-xr-x%202%20runner%20runner%204096%20Jan%2023%2020%3A09%20.upm%0A-rw-r–r–%201%20runner%20runner%20%20579%20Jan%2023%2020%3A00%20_test_runner.py%0A-rw-r–r–%201%20runner%20runner%20%20298%20Jan%2023%2020%3A09%20main.py%0A-rw-r–r–%201%20runner%20runner%20%20%2013%20Jan%2023%2020%3A00%20out.txt%0ACompletedProcess(args%3D’ls%20-al’%2C%20returncode%3D0)%0A” message=”” highlight=”” provider=”manual”/]

ملاحظة: في أثناء تنفيذ الأوامر في سطر الأوامر وحتى انتقالها من جهاز لآخر عن طريق الشبكات، يتم تحويل البيانات إلى بايتات.

والحل الآخر هو أن ندخل الأمر و اختياراته داخل قائمة لنحصل على نفس النتيجة:

[pastacode lang=”python” manual=”import%20subprocess%0Aprocess_1%20%3D%20subprocess.run(%5B’ls’%2C’-al’%5D)%0Aprint(process_1)%0A” message=”” highlight=”” provider=”manual”/]

ومن الجدير بالذكر أن الطريقة الأولى يجب التعامل معها بحذر فيما يخص shell=True، حيث أنها قد تكون عُرضة لاستغلال البرامج التي قد تستخدم معطيات يدخلها المستخدم بنفسه والتي قد تُمكنه من حقن أوامر مباشرة ليتم تنفيذها في سطر الأوامر.

اظهار نتائج اوامر لغة بايثون لنظام التشغيل

لنستخدم الآن وظيفة جديدة تتيح لنا إظهار النتائج والأخطاء إن وجدت والمدخلات بشكل تفصيلي أكثر وكيف يمكننا الإستفادة من كل ذلك:

[pastacode lang=”python” manual=”import%20subprocess%0A%0Aprocess_1%20%3D%20subprocess.Popen(%5B’ls’%2C’-al’%5D%2Cstdin%20%3D%20subprocess.PIPE%2C%0A%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20stdout%20%3D%20subprocess.PIPE%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20stderr%20%3D%20subprocess.PIPE%2C%20shell%20%3D%20True)%0A%0A%0Aoutput%20%2C%20error%20%3D%20process_1.communicate()%0A%0Aprint(output)%0Aprint(error)” message=”” highlight=”” provider=”manual”/]

و المخرجات ستكون كالتالي:

[pastacode lang=”bash” manual=”b’_test_runner.py%5Cnmain.py%5Cnout.txt%5Cn’%0Ab”” message=”” highlight=”” provider=”manual”/]

كما وضحنا سابقا، إن كل عملية لابد من مدخلات ومخرجات وأخطاء إن وجدت. لنقوم بحصر المخرجات والأخطاء قمنا بإضافة:

[pastacode lang=”python” manual=”stdin%20%3D%20subprocess.PIPE%2C%0Astdout%20%3D%20subprocess.PIPE%2C%0Astderr%20%3D%20subprocess.PIPE%0A” message=”” highlight=”” provider=”manual”/]

و ذلك لتفعيل عملية الحصر من داخل الوظيفة. تقوم وظيفة  ()communicate  بفرز المخرجات والأخطاء في متغيرات للاستفادة منها و عرضها:

[pastacode lang=”python” manual=”output%20%2C%20error%20%3D%20process_1.communicate()%0A%0Aprint(output)%0Aprint(error)” message=”” highlight=”” provider=”manual”/]

والآن لنأخذ ما تعلمناه قدما لنوجه مخرجاتنا لملف بدلا من الشاشة:

[pastacode lang=”python” manual=”import%20subprocess%0A%0Afout%20%3D%20open(‘out.txt’%2C’w%2B’)%0A%0Aprocess_1%20%3D%20subprocess.Popen(%5B’ls’%2C’-al’%5D%2Cstdin%20%3D%20subprocess.PIPE%2C%0A%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20stdout%20%3D%20fout%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20stderr%20%3D%20subprocess.PIPE%2C%20shell%20%3D%20True)%0A%0A%0Aoutput%20%2C%20error%20%3D%20process_1.communicate()%0A%0A%0Aprint(output)%0Aprint(error)” message=”” highlight=”” provider=”manual”/]

لاحظ أننا بعد أن قمنا بإنشاء ملف بوضعية القراءة والكتابة قمنا بتوجيه المخرجات من الأمر الى ذلك الملف:

[pastacode lang=”bash” manual=”stdout%20%3D%20fout” message=”” highlight=”” provider=”manual”/]

لاحظ الشاشة:

[pastacode lang=”bash” manual=”None%0Ab”” message=”” highlight=”” provider=”manual”/]

لا يوجد شيء ولكن لنقم بفتح الملف out.txt وعرض محتوياته، سنجد أن محتويات المخرجات تم توجيهها و كتابتها فيه:

[pastacode lang=”bash” manual=”_test_runner.py%0Amain.py%0Aout.txt” message=”” highlight=”” provider=”manual”/]

تمرين

لنقم بتغيير المعامل shell=True إلى False ولنقم بتشغيل البرنامج، لنلاحظ المخرجات في ملف المخرجات. والآن لنقم بكتابة البرنامج  التالي و تشغيله:

[pastacode lang=”python” manual=”import%20subprocess%0A%0Afout%20%3D%20open(‘out.txt’%2C’a%2B’)%0Aferr%20%3D%20open(‘error.txt’%2C’a%2B’)%0A%0Ap1%20%3D%20subprocess.Popen(%5B’ls’%20%2C’ppp’%2C%5D%2Cstderr%20%3D%20ferr%2Cstdout%3D%20fout%2C%20)%0A%0Ap2%20%3D%20subprocess.Popen(%5B’pwd’%5D%2Cstdout%3Dfout)” message=”” highlight=”” provider=”manual”/]

و المخرجات هي None. حيث قمنا بإنشاء ملفين أحدهما، لنكتب عليه المخرجات fout والآخر لكتابة الأخطاء فيه. و في الأسطر التالية:

[pastacode lang=”python” manual=”p1%20%3D%20subprocess.Popen(%5B’ls’%20%2C’ppp’%2C%5D%2Cstderr%20%3D%20ferr%2Cstdout%3D%20fout%2C%20)%0Ap2%20%3D%20subprocess.Popen(%5B’pwd’%5D%2Cstdout%3Dfout)” message=”” highlight=”” provider=”manual”/]

قمنا بإنشاء متغير للعملية بتمرير معاملات في قائمة وهي ls , ppp و نعلم أن ppp هي اختيارات خطأ للأمر ls في أنظمة لينكس و ماك، وقمنا أيضا بعمل متغير لعملية ثانية وقمنا بتمرير أمر عزض اسم الدليل الحالي كنص وتوجيه مخرجاته في ملف المخرجات.

وعند عرض ملف المخرجات:

[pastacode lang=”bash” manual=”%2Fhome%2Frunner” message=”” highlight=”” provider=”manual”/]

وهي نتيجة العملية الثانية p2، ولكن ماذا عن مخرجات العملية الأولى p1 ؟ لنرى ملف الأخطاء:

[pastacode lang=”bash” manual=”ls%3A%20cannot%20access%20’ppp’%3A%20No%20such%20file%20or%20directory” message=”” highlight=”” provider=”manual”/]

نرى أن الأمر ls نتج عنده خطأ أثناء التنفيذ وذلك بأن ppp اختيارات ليست متاحة أصلًا في سطر أوامر لينكس و ماك.

المخرجات كمدخلات لأوامر أخرى

ممتاز جدا،  والآن لنقم بعمل برنامج بسيط يقوم بإنشاء عمليتين، الأولى تقوم بعرض الدليل الحالي من خلال تمرير أمر لينكس pwd كمعامل نصي لها، والعملية الثانية تأخذ مخرجات العملية الأولى وهي مسار الدليل الحالي و تعرض محتوياته بالتفصيل وذلك بتطبيق وتنفيذ معاملها النصي ls -lha عليه:

[pastacode lang=”python” manual=”import%20subprocess%0A%0Ap1%20%3D%20subprocess.Popen(%5B%22pwd%22%5D%2C%20stdout%20%3D%20subprocess.PIPE)%0A%0Ap2%20%3D%20subprocess.Popen(%5B’ls’%2C’-lha’%5D%2Cstdin%20%3D%20p1.stdout)” message=”” highlight=”” provider=”manual”/]

نلاحظ في السطر الأخير بأن تم تحديد مدخلات العملية الثانية p2 بتحديد المعامل stdin = p1.stdout من مخرجات العملية الأولى p1. و تم تنفيذ الأمر في القائمة بالعملية الثانية p2 على ما نتج من العملية الأولى وهي موقع الدليل الحالي. و النتيجة هي عرض محتوياته بالتفصيل.

في الختام نتمنى أنكم قد استمتعتم من الشرح السابق فيما يخص مبادئ مكتبة subprocess والاستفادة منها فيما يخص التحكم في توجيه المخرجات والأخطاء سواء بين العمليات أو للملفات.

 

 

مقالات مشابهة

  • 7 طرق عليك تعلمها لتحسين اختبار البرمجيات

    7 طرق عليك تعلمها لتحسين اختبار البرمجيات

    هل تبحث عن طرق لتحسين اختبار البرمجيات وجعل تلك العملية أكثر كفاءةً وسرعةً مما
    ابراهيم البحيصي
    By ابراهيم البحيصي
    تعرف على المزيد
  • تطبيقات لغة بايثون في إنترنت الأشياء

    تطبيقات لغة بايثون في إنترنت الأشياء

    تطبيقات لغة بايثون في إنترنت الأشياء من المواضيع التي يزداد البحث عنها خلال الوقت
    ابراهيم البحيصي
    By ابراهيم البحيصي
    تعرف على المزيد
  • مكاتب بايثون Playwright لأتمتة الصفحات - بايثونات

    مكتبة Playwright – بديل مايكروسوفت لأتمتة متصفحات الإنترنت

    مكاتب بايثون Playwright لأتمتة الصفحات : مكاتب بايثون بلايورايت : تنوعت أنشطة مايكروسوفت مؤخرًا
    Naser Alostath
    By Naser Alostath
    تعرف على المزيد
  • تصميم قواعد بيانات اوراكل عملي بإستخدام البايثون - بايثونات

    قواعد البيانات الأوراكل والبايثون –كيف نتعامل مع الاوراكل من كود بايثون

    قواعد البيانات الأوراكل هي أحد أقوى قواعد البيانات، وتعتمد عليها الكثير من الشركات عالميًا.
    ابراهيم البحيصي
    By ابراهيم البحيصي
    تعرف على المزيد

One Comment

Comments are closed.