هل من الممكن إنشاء إطار مكدس بيثون برمجيا وبدء التنفيذ في نقطة تعسفية في التعليمات البرمجية؟

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

سؤال

هل من الممكن إنشاء مكدس برمجيا (واحد أو أكثر من إطارات المكدس) في CPYTHON وبدء التنفيذ في نقطة رمز تعسفية؟ تخيل السيناريو التالي:

  1. لديك محرك سير عمل حيث يمكن كتابة سير العمل في Python مع بعض البنيات (مثل المتفرعة أو الانتظار / الانضمام) التي تدعو إلى محرك سير العمل.

  2. مكالمة حظر، مثل الانتظار أو الانضمام، قم بإعداد شرطا للمستمع في محرك إرسال الأحداث مع متجر دعم مستمر من نوع ما.

  3. لديك برنامج نصي لسير العمل، الذي يستدعي حالة الانتظار في المحرك، في انتظار بعض الشرط الذي سيتم الإشارة لاحقا. هذا يحدد المستمع في محرك إرسال الأحداث.

  4. تستمر حالة سير العمل في سير العمل وإطارات المكدس ذات الصلة بما في ذلك برنامج مكافحة البرنامج (أو الحالة المكافئة) - لأن حالة الانتظار قد تحدث أيام أو أشهر لاحقة.

  5. في المؤقتة، قد يتم إيقاف تشغيل محرك سير العمل وإعادة تشغيله، مما يعني أنه يجب أن يكون من الممكن تخزين وإعادة بناء سياق برنامج عمل سير العمل وإعادة بناءه.

  6. يقوم المحرك بإرسال الحدث يطلق الحدث الذي يلتقط فيه حالة الانتظار.

  7. يقرأ محرك سير العمل الحالة المتسلسلة ومكدسة وإعادة بناء مؤشر ترابط مع المكدس. ثم يستمر في التنفيذ عند الإشارة التي تم فيها استدعاء خدمة الانتظار.

السؤال

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

يحرر: لتوضيح "مترجم الثعبان غير المصيد"، لا أمانع استخدام API C (هل هناك معلومات كافية في Pythreadstate للقيام بذلك؟) لكنني لا أريد أن أذهب بدس حول Internals of the Python المترجم والضغط واحد تعديل.

تحديث: من بعض التحقيق الأولي، يمكن للمرء الحصول على سياق التنفيذ مع PyThreadState_Get(). وبعد هذا إرجاع حالة الموضوع في PyThreadState (المعرفة في pystate.h)، والتي لديها إشارة إلى إطار المكدس في frame. وبعد يتم عقد إطار مكدس في بنية Typedef'd PyFrameObject, ، والتي يتم تعريفها في frameobject.h. PyFrameObject لديه مجال f_lasti (الدعائم ل بوبين) الذي يحتوي على عداد برنامج يتم التعبير عنه كإزاحة من بداية كتلة الكود.

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

المشاكل الثلاثة المتبقية هي:

  • ستستخدم حالة المعاملات و "الملحمة"، والتي ربما يمكن أن يتحقق من خلال نوع من القرصنة Metaclass واحدة لبناء مخطط O / R. قمت ببناء نموذج أولي مرة واحدة، لذلك لدي فكرة عاطل عن كيفية تحقيق ذلك.

  • تسلسل بقوة الدولة المعاملات والسكان المحليين التعسفي. قد يتم إنجاز هذا بالقراءة __locals__ (وهو متاح من إطار المكدس) وإنشاء مكالمة برمجيا للمخلل. ومع ذلك، لا أعرف ماذا، إن وجدت، قد يكون هناك هنا.

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

تحديث 2: PyCodeObject (code.h) لديه قائمة Addr (f_lasti) -> تعيينات رقم الخط في PyCodeObject.co_lnotab (تصحيح لي إذا كان الخطأ هنا). قد يتم استخدام هذا لتسهيل عملية الترحيل لتحديث سير العمل إلى إصدار جديد، حيث يمكن تعيين مؤشرات التعليم المجمدة إلى المكان المناسب في البرنامج النصي الجديد، تم القيام به من حيث أرقام السطر. لا تزال فوضوي تماما ولكن أكثر واعدة قليلا.

تحديث 3: أعتقد أن الإجابة على ذلك قد يكون بايثون بلا حدود. يمكنك تعليق المهام وتسليطها. أنا لم أعمل ما إذا كان هذا سيعمل أيضا مع المكدس أيضا.

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

المحلول 5

مع CPYTHON القياسية هذا معقد من قبل مزيج من بيانات C و Python في المكدس. ستحتاج إعادة بناء مكدس المكالمات إلى إعادة بناء مكدس C في نفس الوقت. هذا يضعه حقا في سلة شاقة للغاية لأنه من المحتمل أن يكون بإمكانه إيقافه بإصدار إصدارات محددة من CPYTHON.

يسمح Python بدون تكثيف بالمهام التي سيتم بلوغها، والتي تعطي معظم القدرة المطلوبة من الصندوق.

نصائح أخرى

يقوم Bindings Python Expat Python المدرجة في توزيع Python العادي بإنشاء إطارات المكدس بالبرنامجي. تحذير رغم ذلك، فإنه يعتمد على واجهات برمجة التطبيقات غير الموثقة والخاصة.

http://svn.python.org/view/python/trunk/modules/pyexpat.c؟rev=64048&view=Auto.

ما تريد عموما مستمرات، والتي أراها هي بالفعل علامة على هذا السؤال.

إذا كان لديك القدرة على العمل مع جميع التعليمات البرمجية في النظام، فقد ترغب في محاولة القيام بذلك بهذه الطريقة بدلا من التعامل مع Interperter Stack Interals. لست متأكدا من مدى سهولة استمرار هذا الأمر.

http://www.ps.uni-sb.de/~duchier/python/continuations.html.

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

بمعنى آخر: اجعل مستوى التطبيق الخاص بك، مكدس.

ربما يكون بيثون عديم الثدي أفضل ... إذا كنت لا تمانع في الانتظار تماما لتوزيع Python مختلف. stackless يمكن تسلسل كل شيء في بيثون، بالإضافة إلى مهامهم. إذا كنت ترغب في البقاء في توزيع بيثون القياسي، فسأستعبه شبت, ، والتي يمكن أن تسلسل تقريبيا أي شيء في بيثون.

>>> import dill
>>> 
>>> def foo(a):
...   def bar(x):
...     return a*x
...   return bar
... 
>>> class baz(object):
...   def __call__(self, a,x):
...     return foo(a)(x)
... 
>>> b = baz()
>>> b(3,2)
6
>>> c = baz.__call__
>>> c(b,3,2)
6
>>> g = dill.loads(dill.dumps(globals()))
>>> g
{'dill': <module 'dill' from '/Library/Frameworks/Python.framework/Versions/7.2/lib/python2.7/site-packages/dill-0.2a.dev-py2.7.egg/dill/__init__.pyc'>, 'c': <unbound method baz.__call__>, 'b': <__main__.baz object at 0x4d61970>, 'g': {...}, '__builtins__': <module '__builtin__' (built-in)>, 'baz': <class '__main__.baz'>, '_version': '2', '__package__': None, '__name__': '__main__', 'foo': <function foo at 0x4d39d30>, '__doc__': None}

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

هنا dill تخليل جلسة مترجم كله ...

>>> # continuing from above
>>> dill.dump_session('foobar.pkl')
>>>
>>> ^D
dude@sakurai>$ python
Python 2.7.5 (default, Sep 30 2013, 20:15:49) 
[GCC 4.2.1 (Apple Inc. build 5566)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>> import dill
>>> dill.load_session('foobar.pkl')
>>> c(b,3,2)
6

dill لديها أيضا بعض الأدوات الجيدة لمساعدتك في فهم ما يسبب فشل التخلف عند فشل التعليمات البرمجية الخاصة بك.

طلبت أيضا من أين يتم استخدامه لحفظ الدولة المترجمية؟

ipython. يمكن استخدام dill لحفظ جلسة الترجمة إلى ملف. https://nbtest.herokuapp.com/github/ipython/ipython/blob/master/examples/parallel/us٪20dill.pynb.

كلبتو الاستخدامات dill لدعم التخزين المؤقت في الذاكرة أو القرص أو إلى قاعدة البيانات التي تتجنب إعادة التحويل. https://github.com/uqfoundation/klepto/blob/master/tests/test_cache_info.py.

الصوفي الاستخدامات dill لحفظ نقاط التفتيش لمهام التحسين الكبيرة عن طريق حفظ حالة المحسن كما هو قيد التقدم. https://github.com/uqfoundation/mystic/blob/master/tests/test_solver_state.py.

هناك بضع حزم أخرى تستخدم dill لحفظ حالة الكائنات أو الجلسات.

يمكنك الاستيلاء على إطار المكدس الموجود من خلال إلقاء استثناء ويتخطى إطارا واحدا إلى جانب Traceback. المشكلة هي عدم وجود طريقة لاستئناف التنفيذ في منتصف (frame.f_lasti) من كتلة الكود.

"الاستثناءات القابلة للاستيلاء" هي فكرة لغة مثيرة للاهتمام حقا، على الرغم من أنها صعبة التفكير في طريقة معقولة يمكن أن تتفاعل مع "محاولة / أخيرا" الموجودة في بيثون و "مع كتل".

في الوقت الحالي، فإن الطريقة العادية للقيام بذلك هي ببساطة استخدام المواضيع لتشغيل سير العمل الخاص بك في سياق منفصل لمراقبها. (أو coloutines / bredlets إذا كنت لا تمانع في تجميعها في).

لدي نفس النوع من المشكلة لحلها. وأتساءل ما قرر الملصق الأصلي القيام به.

مطالبات تكثيف يمكنها أن تخلل المهام طالما عدم وجود مكدس C مرتبط "المرهونة" (المرهونة هو خياري من الصياغة).

ربما سأستخدم Eventlet ومعرفة بعض الطرق "حالة" التخليل "، وأنا لا أريد حقا كتابة آلة حالة واضحة على الرغم من ..

ماذا عن استخدام. جبليب?

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

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