التخزين المؤقت لكائنات regex المترجمة في بيثون؟

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

  •  09-06-2019
  •  | 
  •  

سؤال

في كل مرة يتم فيها استيراد ملف بايثون يحتوي على كمية كبيرة من التعبيرات العادية الثابتة، يتم إنفاق دورات وحدة المعالجة المركزية في تجميع السلاسل في أجهزة الحالة التمثيلية الخاصة بها في الذاكرة.

a = re.compile("a.*b")
b = re.compile("c.*d")
...

سؤال:هل من الممكن تخزين هذه التعبيرات العادية في ذاكرة تخزين مؤقت على القرص بطريقة مجمعة مسبقًا لتجنب الاضطرار إلى تنفيذ مجموعات regex في كل عملية استيراد؟

يؤدي تخليل الكائن ببساطة إلى ما يلي، مما يؤدي إلى حدوث التجميع على أي حال:

>>> import pickle
>>> import re
>>> x = re.compile(".*")
>>> pickle.dumps(x)
"cre\n_compile\np0\n(S'.*'\np1\nI0\ntp2\nRp3\n."

و re الكائنات غير قابلة للتنظيم:

>>> import marshal
>>> import re
>>> x = re.compile(".*")
>>> marshal.dumps(x)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
ValueError: unmarshallable object
هل كانت مفيدة؟

المحلول

هل من الممكن تخزين هذه التعبيرات العادية في ذاكرة تخزين مؤقت على القرص بطريقة مجمعة مسبقًا لتجنب الاضطرار إلى تنفيذ مجموعات regex في كل عملية استيراد؟

ليس بسهولة.سيتعين عليك كتابة برنامج تسلسلي مخصص يتم ربطه بملف C sre تنفيذ محرك بايثون regex.أي فوائد للأداء سوف يفوقها إلى حد كبير الوقت والجهد المطلوب.

أولاً، هل قمت بالفعل بتعريف الكود؟أشك في أن تجميع التعابير المنطقية يمثل جزءًا مهمًا من وقت تشغيل التطبيق.تذكر أنه يتم تجميعها فقط في المرة الأولى التي يتم فيها استيراد الوحدة في التنفيذ الحالي - وبعد ذلك، يتم تخزين الوحدة وسماتها مؤقتًا في الذاكرة.

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

أخيرًا، يمكنك تجميع التعابير المنطقية في أجهزة الحالة المستندة إلى لغة C ثم ربطها بوحدة ملحقة.على الرغم من أن الحفاظ على هذا قد يكون أكثر صعوبة، إلا أنه سيؤدي إلى إزالة تجميع regex بالكامل من تطبيقك.

نصائح أخرى

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

أولًا، هذا قيد واضح في وحدة إعادة بايثون.إنه يسبب حدًا لمدى وحجم التعبيرات العادية المعقولة.يكون الحد أكبر مع العمليات طويلة الأمد وأصغر مع العمليات قصيرة العمر مثل تطبيقات سطر الأوامر.

لقد نظرت إليها منذ عدة سنوات ومن الممكن استخراج نتيجة التجميع وخلطها ثم فكها وإعادة استخدامها.تكمن المشكلة في أنها تتطلب استخدام الأجزاء الداخلية sre.py وبالتالي لن تعمل على الأرجح في إصدارات مختلفة من لغة python.

أرغب في الحصول على هذا النوع من الميزات في صندوق الأدوات الخاص بي.أود أيضًا أن أعرف ما إذا كان هناك أي وحدات منفصلة يمكن استخدامها بدلاً من ذلك.

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


import re
import shelve
a_pattern = "a.*b"
b_pattern = "c.*d"
a = re.compile(a_pattern)
b = re.compile(b_pattern)

x = shelve.open('re_cache')
x[a_pattern] = a
x[b_pattern] = b
x.close()

# ...
x = shelve.open('re_cache')
a = x[a_pattern]
b = x[b_pattern]
x.close()

يمكنك بعد ذلك إنشاء فئة مجمعة لطيفة تتعامل تلقائيًا مع التخزين المؤقت نيابةً عنك بحيث تصبح شفافة للمستخدم...تمرين متروك للقارئ.

افتح /usr/lib/python2.5/re.py وابحث عن "def_compile".ستجد آلية ذاكرة التخزين المؤقت الداخلية لـ re.py.

من الممكن وضع كل تعبير عادي (أو مجموعة من التعبيرات العادية) في ملف منفصل ثم استيراد الملف الذي تحتاجه ديناميكيًا باستخدام الوحدة النمطية imp.أشك في أن حجمه جيد جدًا ولكنه قد يكون ما تحتاجه.

همم،

لا الرف استخدام المخلل؟

على أية حال، أنا أتفق مع الإجابات السابقة.نظرًا لأنه تتم معالجة الوحدة مرة واحدة فقط، أشك في أن تجميع التعبيرات العادية سيكون بمثابة عنق الزجاجة لتطبيقك.ووحدة Python re شريرة بسرعة لأنها مشفرة بلغة C :-)

لكن الخبر السار هو أن بايثون لديها مجتمع لطيف، لذلك أنا متأكد من أنه يمكنك العثور حاليًا على شخص يقوم باختراق ما تحتاجه تمامًا.

بحثت في جوجل لمدة 5 ثواني ووجدت: http://home.gna.org/oomadness/en/cerealizer/index.html.

لا أعرف ما إذا كان سيفعل ذلك ولكن إذا لم يكن كذلك، حظًا سعيدًا في بحثك :-)

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