بسم الله الرحمن الرحيم
السلام عليكم ورحمة الله وبركاته
بعض الشرح عن subprocess.Popen .
بعض المعلومات المبسطة لن أدخل بأشياء قد تصدم الأخرين مثل مجرى الدخل والخرج ومجرى الخطأ و ...إلخ لا تشغلو بالكم بهذه المسميات على الأقل في موضوعي هذا الذي أريد أن أوضحه فقط هو تصورو أن هناك إنبوبين واحد إسمه stdout و واحد إسمه stderr إذا تم تنفيذ الأمر بنجاح يتم إرسال المعلومات عن طريق إنبوب stdout اما إذا لم ينجح تنفيذ الأمر يتم إرسال المعلومات عن طريق الإنبوب stderr وهذا فقط لتبسيط الأمور حتى نكمل الشرح وطبعا أنا أتكلم عن لينكس لا أعلم عن باقي الأنظمة.
الذي نريد ان نتعلمه من خلال subprocess.Popen هو تنفيذ أمر ما ثم إذا صح التعبير حفظ الناتج الذي يخرج من الأنبوبين في متغير أو متغيرين ثم بعدها ممكن الإستفادة من الناتج على حسب ما نريد طبعا كل هذا سأحاول شرحه بطريقة مبسطة وبالصور .
لنبدأ :
1-طلبت تنفيذ أمر echo hi ثم وضعت لكل من stdout و stderr قيمة والتي هي subprocess.PIPE وحفظت النتيجة في متغير سميته out.
2-نلاحظ ان قيمة out هي كائن من نوع subprocess.Popen .
3-إذا صح التعبير قمت بتحويل هذا الكائن إلى tuple فيها قيمتين وهم مخرجات stdout و stderr .
4-نلاحظ القيمتين ,القيمة الاول هي مخرجات stdout ولهذا نجد كلمة hi لأن الامر تم تنفيذه بنجاح أما القيمة الثانية هي مخرجات stderr وهي فارغة الأن لأن الامر تم تنفيذه من دون أي خطأ .
5-قمت بطلب فقط أول قيمة من ال tuple والتي هي مخرجات stdout .
6-إستخدمت دالة strip لإزالت المسافات الفارغة نلاحظ كان سابقا هناك n\ إختصار لسطر جديد .
7-قمت بإزالت المسافات الفارغة ثم حولت القيمة إلى نص من نوع str حتى اتعامل معه بشكل أريح على العموم هذا ما سنحتاجه عادتا أي أننا عادتا نتعامل مع نصوص من نوع str .
ممكن إختصار الامر وطلب مخرجات stdout بسطر واحد نلاحظ [0] اي أننا طلبنا أول عنصر من ال tuple .
ذات الشيء لاكني تعمدت وضع تنفيذ امر غير صحيح لهذا طلبت ثاني عنصر من ال tuple .
أيضا ذات المبدأ لاكني بدل طلب كل قيمة لوحدها من خلال موقعها في ال tuple قمت بحفظ اول قيمة في ال tuple في متغير سميته out وثاني قيمة حفظتها في متغير سميته error .
فقك مثال بسيط لكيف ممكن أن نستفيد من الأمر إذا كان عدد الاحرف في متغير out أكبر من صفر هذا يعني ان الأمر تم بنجاح إطبع success ثم إطبع بعدها الناتج ,أما غير ذالك إطبع Fail والخطأ الذي ظهر ,ملاحظة الصورة التي قبلها ذات المبدأ.
أيضا ذات المبدأ انا فقط إستبدلت دالة print بنافذة تظهر فيها المخرجات وهذا أمر ليس موضوعنا اﻷن انا فقط أضع بعض أمثلة عن كيفية الإستفادة من ما أشرحه.
أخيرا إذا أردنا أن تخرج النتيجة دائما من stdout نستبدل subprocess.PIPE ب subprocess.STOUT في stderr نلاحظ ان المخرجات من stderr ستصبح دائما None والمخرجات ستخرج دائما من خلال stdout بغض النظر عن صحة تنفيذ الامر من عدمه.
أخيرا أريد أن أذكر أن في الإصدارات الحديثة من بايثون أظن إصدار 3.5 و أعلى تم إضافة subprocess.run وهي توفر السهولة وتجمع اكثر من شيء مثلا ستغنيك عن subprocess.call و subprocess.Popen و بعض الأشياء ...إلخ .
لاكن للتوافقية من المهم أن تعرف الإثنين لأنك لا تعرف من يستخدم السكربت أو البرنامج الخاص بك أي إصدار يستخدم لهذا Popen قد تكون أكثر توافقية مع إصدارات بايثون على العموم لا أعرف إذا ساشرح عن subprocess.run لاحقا إن شاء الله سأفعل لاكن لست متأكد .