سؤال

أحاول استخدام وحدة Python-Daemon. يزود فئة Daemon.DaemonContext لتصوير البرنامج النصي بشكل صحيح. على الرغم من أنني أستهدف في المقام الأول Python 2.6+ ، إلا أنني أرغب في الحفاظ على التوافق مع الإصدار 2.4.

يدعم Python 2.5 استيراد السياقات من مستقبل, ، ولكن بيثون 2.4 ليس لديه مثل هذا المرفق. لقد اعتقدت أنه يمكنني فقط التقاط أي خطأ يثيره البيان مع الإدخال والخروج من السياق يدويًا مقابل 2.4 ، لكن لا يبدو لي أن أرفع بناء الجملة.

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

فما باللك إذا كان Python 2.4 لا يمكن تشغيل Python-Daemon ؛ أود على الأقل أن أتمكن من التقاط الخطأ وتنفيذ احتياطي أو شيء من هذا القبيل.

شكرا على المساعدة.

#!/usr/bin/python2.4
from __future__ import with_statement
# with_statement isn't in __future__ in 2.4.
# In interactive mode this raises a SyntaxError.
# During normal execution it doesn't, but I wouldn't be able to catch it
# anyways because __future__ imports must be at the beginning of the file, so
# that point is moot.


class contextable(object):
    def __enter__(self):
        print('Entering context.')
        return None
    def __exit__(self, exc_type, exc_val, exc_tb):
        print('Exiting context.')
        return False

def spam():
    print('Within context.')

context = contextable()

try:
    with context: # This raises an uncatchable SyntaxError.
        spam()
except SyntaxError, e: # This is how I would like to work around it.
    context.__enter__()
    try:
        spam()
    finally:
        context.__exit__(None, None, None)
هل كانت مفيدة؟

المحلول

SyntaxError يتم تشخيصه من قبل برنامج التحويل البرمجي Python أثناء تجميعه - من المفترض أنك تحاول "التقاط" من الكود الذي يتم تجميعه كجزء من نفس الوحدة (على سبيل المثال ، هذا ما تفعله في عينة الكود الخاصة بك) ، لذلك بالطبع لن ينجح ذلك - لم يتم تجميع رمز "الصيد" الخاص بك بعد (لأن التجميع قد تم إنهاءه دون جدوى) بحيث لا يمكنه التقاط أي شيء.

تحتاج إلى التأكد من تجميع الكود الذي قد يكون له خطأ في بناء الجملة في وقت لاحق من رمز الصيد - إما وضعه في وحدة منفصلة تستوردها في try بند ، أو في سلسلة لك compile مع المدمج في هذا الاسم (يمكنك لاحقًا تنفيذ رمز BYTECNOD الناتج عن compile اتصل ، إذا أنهى بنجاح).

لا يبدو أي احتمال جيدًا لأغراضك ، على ما أعتقد. أظن أن استخدام وحدتين منفصلتين (وربما الاختيار بينهما اعتمادًا على فحص "Do This Compile" ، لكن فحص الإصدار يبدو أكثر نظافة بالنسبة لي) هو الحل الوحيد "النظيف" ، للأسف.

يحرر: فيما يلي كيفية تجربة/باستثناء عمليات فحص الإصدار:

$ python2.4 -mtimeit 'try:
  compile("with x: pass", "", "exec")
except SyntaxError: x=1
else: x=2'
100000 loops, best of 3: 10.8 usec per loop
$ python2.6 -mtimeit 'try:
  compile("with x: pass", "", "exec")
except SyntaxError: x=1
else: x=2'
10000 loops, best of 3: 40.5 usec per loop

$ python2.4 -mtimeit -s'import sys' 'if sys.version>="2.5": x=2
else: x=1'
1000000 loops, best of 3: 0.221 usec per loop
$ python2.6 -mtimeit -s'import sys' 'if sys.version>="2.5": x=2
else: x=1'
10000000 loops, best of 3: 0.156 usec per loop

كما ترى ، فإن الإصدار الذي أعتبره نظافة هو 10.8 / 0.221, ، ما يقرب من 50 مرة أسرع ، في 2.4 ، و 40.5 / 0.156, ، ما يقرب من 260 مرة أسرع ، في 2.6. بشكل عام (مع استثناءات نادرة) ، سيتحول نهج نظيف (أي ، "Pythonic") إلى أن يكون أفضل من ذلك في Python - غالبًا ، على الأقل جزء من السبب هو أن مطوري Python الأساسي يركزون على تسهيل وتشجيع استخدام البنيات التي يحبونها ، بدلاً من أن تكون بنيات تكرهها.

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