أنابيب بايثون - ماذا يحدث عند قراءة المخرجات بشكل متزايد

StackOverflow https://stackoverflow.com/questions/1612349

  •  06-07-2019
  •  | 
  •  

سؤال

وفق قسم في هذا الكتاب الذي يفترض أنه دقيق,

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

 def open_gunzip(filename):
     cmd = 'gunzip -c ' + filename
     fp = os.popen(cmd)
     return fp

إذا قرأت خطوطًا من FP واحدة في وقت واحد ، you never have to store the uncompressed file in memory or on disk.

ربما أفسر هذا بشكل خاطئ، لكنني لا أرى كيف يكون هذا ممكنًا.لا يمكن لبايثون أن يكون لديها أي وسيلة لإيقاف gunzip مؤقتًا في منتصف الطريق خلال عرض النتائج، أليس كذلك؟أفترض أن gunzip لن يتم حظره حتى تتم قراءة سطر من الإخراج قبل الاستمرار في إخراج المزيد من الأسطر، لذلك يجب أن يلتقط بعض المخزن المؤقت كل هذا (سواء داخل مترجم Python أو في نظام التشغيل، سواء في الذاكرة أو على القرص) )، مما يعني أنه يتم تخزين الملف غير المضغوط مكان ما بالكامل... أليس كذلك؟

هل كانت مفيدة؟

المحلول

افتراضك خاطئ.لا يحتاج gunzip إلى رؤية الملف بأكمله لفك ضغطه.اقرأ تنسيق الملف المضغوط.يوجد دليل به إزاحات للمكونات الفردية.

من الممكن فك ضغط الملف إلى أجزاء.

"يتم تخزين الملف غير المضغوط بالكامل في مكان ما... أليس كذلك؟"

ليس بالضرورة.لست متأكدًا من سبب افتراضك له أو من أين قرأته.

يمكن حظر جميع مكالمات الإدخال/الإخراج ذات المستوى المنخفض.الكتابة في gunzip - عند الكتابة إلى أنبوب - يمكن أن يتم حظرها عندما يكون المخزن المؤقت للأنبوب ممتلئًا.هذه هي الطريقة التي يتم بها تعريف الإدخال/الإخراج إلى الأنبوب.كتل الإدخال/الإخراج للأنابيب.

تحقق من صفحات الرجل للأنابيب للحصول على التفاصيل.

If a process attempts to read from an empty pipe, then read(2) will
الحظر حتى تتوفر البيانات.
full pipe (see below), then write(2) blocks until sufficient data has
غير مانع
I/O is possible by using the fcntl(2) F_SETFL operation to enable the
O_NONBLOCK علامة حالة الملف المفتوح.

نصائح أخرى

هذا حقا يأتي من gunzip التنفيذ وليس من بايثون.هو مكتوب في C.ربما يستخدم fwrite() من C stdio.h لكتابة مخرجاته.

libc6 التنفيذ الذي أستخدمه يقوم تلقائيًا بإنشاء مخزن مؤقت للإخراج، وعندما يتم ملؤه، يتم تشغيله fwrite() حتى يتمكن من كتابة المزيد.

ليست بايثون هي التي تم تعليقها gunzip, ، هو أن النواة ستتوقف عن التنفيذ gunzip عندما يحاول الكتابة (باستخدام write() syscall) إلى مخزن مؤقت كامل.هذا يسمي حظر على IO.تحتفظ النواة بمخزن مؤقت داخلي يربط طرفي خط الأنابيب، بشكل مستقل عن أي تخزين مؤقت يحدث في أي عمليات تكتب إلى الأنبوب أو تقرأ منه.

سيتم حظر Python بالمثل عند القراءة من أنبوب يحتوي على مخزن مؤقت فارغ، أي.الذي لا يحتوي حاليا على أي بيانات من gunzip مكتوب عليه.

يمكن اعتبار الأنابيب حلاً لمشكلة مشكلة المنتج والمستهلك.

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top