وحدة الهيكل في بيثون
ال وحدة الهيكل في بايثون يسمح لك بالعمل مع البيانات الثنائية من خلال توفير وظيفة للتحويل بين قيم Python والبيانات الثنائية ذات النمط C. وهذا مفيد بشكل خاص عند التعامل مع تنسيقات الملفات الثنائية أو بروتوكولات الشبكة. وتشمل الميزات الرئيسية ما يلي:
- التعبئة تحويل قيم بايثون إلى بيانات ثنائية (بايت).
- التفريغ تحويل البيانات الثنائية مرة أخرى إلى قيم بايثون.
- سلاسل التنسيق تحديد كيفية تعبئة/تفكيك البيانات باستخدام أكواد التنسيق (على سبيل المثال، i للأعداد الصحيحة f للأعدادات).
الطرق في struct.pack()
1.Struct.pack (): يقوم بتحويل قيم Python إلى تنسيق ثنائي معبأ. تحدد سلسلة التنسيق (fmt) تخطيط البيانات المجمعة ويتم تجميع القيم اللاحقة (v1 v2 ...) وفقًا لهذا التنسيق. بناء الجملة:
struct.pack(fmt v1 v2 ...)
- fmt : سلسلة تنسيق تحدد كيفية تعبئة البيانات.
- v1 v2 ...: القيم التي سيتم تعبئتها وفقًا للتنسيق المحدد.
import struct # pack values into binary var = struct . pack ( 'hhl' 1 2 3 ) print ( var ) var = struct . pack ( 'iii' 1 2 3 ) print ( var )
الإخراج
b'x01x00x02x00x00x00x00x00x03x00x00x00x00x00x00x00' b'x01x00x00x00x02x00x00x00x03x00x00x00'
التفسير: "hhl" يعني عددين صحيحين قصيرين (h 2 بايت لكل منهما) متبوعًا برقم طويل (عادةً 4 أو 8 بايت حسب النظام الأساسي). "ثالثا" حزم ثلاثة أعداد صحيحة 4 بايت. الإخراج بالبايت (b'') يمثل التشفير الثنائي للقيم.
2.struct.unpack(): يقوم بتحويل البيانات الثنائية المعبأة مرة أخرى إلى قيم بايثون. يأخذ سلسلة تنسيق (fmt) وسلسلة ثنائية معبأة ويعيد مجموعة من القيم غير المجمعة. بناء الجملة:
struct.unpack (سلسلة FMT)
- فمت: سلسلة تنسيق تحدد كيفية تفريغ البيانات.
- خيط: البيانات الثنائية المعبأة التي تحتاج إلى تفكيكها.
import struct var = struct . pack ( '?hil' True 2 5 445 ) print ( var ) tup = struct . unpack ( '?hil' var ) print ( tup ) var = struct . pack ( 'qf' 5 2.3 ) print ( var ) tup = struct . unpack ( 'qf' var ) print ( tup )
الإخراج
b'x01x00x02x00x05x00x00x00xbdx01x00x00x00x00x00x00' (True 2 5 445) b'x05x00x00x00x00x00x00x0033x13@' (5 2.299999952316284)
توضيح: يحزم هذا المثال أولاً قيمة منطقية (؟) وقصيرة (h) وعددًا صحيحًا (i) وطويلًا (l) في وحدات البايت. ثم يتم استخدام struct.unpack() لتحويلها مرة أخرى إلى قيم Python. الجزء الثاني يحزم عددًا صحيحًا طويلًا (q) وعائمًا (f) ثم يفكهما مرة أخرى. لاحظ كيف يصبح 2.3 2.299999952... بسبب دقة التعويم.
3. الهيكل.calcsize (): تقوم بإرجاع الحجم (بالبايت) للبنية المقابلة لسلسلة التنسيق. من المفيد تحديد مقدار المساحة المطلوبة لتخزين البيانات المعبأة. بناء الجملة:
الهيكل.calcsize (FMT)
- fmt: سلسلة تنسيق تحدد تخطيط البيانات.
import struct print ( struct . calcsize ( '?hil' )) print ( struct . calcsize ( 'qf' ))
الإخراج
16 12
شرح: '؟هيل' يتطلب 16 بايت و "QF" يحتاج إلى 12 بايت حسب المحاذاة والنظام الأساسي.
4. struct.pack_into() و struct.unpack_from(): تسمح لك هذه الطرق بحزم البيانات وتفريغها مباشرةً من/إلى المخزن المؤقت بدءًا من إزاحة معينة. تعتبر هذه مفيدة بشكل خاص عند التعامل مع مخازن الذاكرة المؤقتة المخصصة مسبقًا أو عند العمل مع البيانات الثنائية المخزنة في الذاكرة.
بناء جملة struct.pack_into():
struct.pack_into(إزاحة المخزن المؤقت fmt v1 v2 ...)
- fmt: سلسلة تنسيق تحدد تخطيط البيانات.
- المخزن المؤقت: مخزن مؤقت قابل للكتابة (على سبيل المثال، ctypes.create_string_buffer).
- الإزاحة: موضع البداية في المخزن المؤقت حيث تبدأ التعبئة.
- v1 v2 ...: القيم التي سيتم تعبئتها في المخزن المؤقت.
بناء جملة struct.unpack_from():
struct.unpack_from(إزاحة المخزن المؤقت fmt=0)
- فمت: سلسلة تنسيق تحدد تخطيط البيانات.
- المخزن المؤقت: المخزن المؤقت الذي يحتوي على البيانات المعبأة.
- إزاحة: موضع البداية من حيث يبدأ التفريغ (اختياري)
import struct import ctypes # Allocate buffer size = struct . calcsize ( 'hhl' ) buff = ctypes . create_string_buffer ( size ) # Pack into buffer struct . pack_into ( 'hhl' buff 0 2 2 3 ) # Unpack from buffer res = struct . unpack_from ( 'hhl' buff 0 ) print ( res )
الإخراج
(2 2 3)
توضيح: هنا يتم إنشاء مخزن مؤقت باستخدام ctypes. struct.pack_into() يقوم بإدراج القيم في هذا المخزن المؤقت عند الإزاحة المحددة (0 في هذه الحالة). struct.unpack_from() ثم يقرأ البيانات مرة أخرى من المخزن المؤقت.
تأثير ترتيب التنسيق
يمكن أن يؤدي ترتيب أحرف التنسيق إلى تغيير الإخراج المعبأ بسبب الحشو والمحاذاة. يؤثر هذا على محتوى البايت وحجم النتيجة.
Python import struct var = struct . pack ( 'bi' 56 0x12131415 ) print ( var ) print ( struct . calcsize ( 'bi' )) var = struct . pack ( 'ib' 0x12131415 56 ) print ( var ) print ( struct . calcsize ( 'ib' ))
الإخراج
b'8x00x00x00x15x14x13x12' 8 b'x15x14x13x128' 5
الشرح: 'bi' (بايت int) قد يتضمن الحشو بعد البايت بينما "ib" (بايت كثافة العمليات) لا يحتاج إليها. يوضح اختلاف الحجم (8 مقابل 5) مدى تأثير المحاذاة على تخطيط الذاكرة.
التعامل مع الأخطاء
إذا تم استخدام نوع بيانات خاطئ مع struct.pack()، فسيحدث خطأ struct. استخدم حاول باستثناء التعامل مع مثل هذه الحالات بأمان.
Python import struct try : struct . pack ( 'h' 'invalid' ) # Wrong type 'invalid' is a string but 'h' expects an integer except struct . error as e : print ( f 'Struct Error: { e } ' )
الإخراج
Struct Error: required argument is not an integer
توضيح: يوضح هذا معالجة الأخطاء عند استخدام البنية. يتوقع 'h' عددًا صحيحًا قصيرًا ولكن يتم إعطاء سلسلة ("غير صالحة") تسبب خطأ في البنية. تلتقط كتلة المحاولة باستثناء الخطأ وتطبع رسالة ذات معنى.
مرجع https://docs.python.org/2/library/struct.html
إنشاء اختبار