
एक क्रॉस-वर्जन पाइथन बाइटकोड डीकंपाइलर
|buildstatus| |Pypi Installs| |Latest Version| |Supported Python Versions|
|packagestatus|
.. contents::
एक मूल Python क्रॉस-वर्जन डीकंपाइलर और फ्रैगमेंट डीकंपाइलर। decompyle, uncompyle, और uncompyle2 का उत्तराधिकारी।
मैंने ब्लैकहैट एशिया 2024 <https://youtu.be/H-7ZNrpsV50?si=nOaixgYHr7RbILVS>_ में इस पर एक व्याख्यान दिया।
uncompyle6 Python बाइटकोड को वापस समकक्ष Python स्रोत कोड में अनुवादित करता है। यह Python संस्करण 1.0 से 3.8 तक के बाइटकोड को स्वीकार करता है, जो Python रिलीज़ के 24 वर्षों से अधिक की अवधि को कवर करता है। हम Dropbox के Python 2.5 बाइटकोड और कुछ PyPy बाइटकोड भी शामिल करते हैं।
ठीक है, मैं कहूँगा: यह सॉफ्टवेयर अद्भुत है। यह आपके सामान्य हैकी डीकंपाइलर से कहीं अधिक है। compiler_ तकनीक का उपयोग करके, प्रोग्राम निर्देशों से प्रोग्राम का एक पार्स ट्री बनाता है; ऊपरी स्तरों पर नोड्स जो थोड़े-बहुत Python AST से आ सकते हैं, ऐसे दिखते हैं। इसलिए हम वास्तव में Python बाइटकोड के अनुभागों में क्या चल रहा है, इसे वर्गीकृत और समझ सकते हैं।
इस पर निर्माण करते हुए, एक और चीज़ जो इसे अन्य CPython बाइटकोड डीकंपाइलरों से अलग बनाती है, वह यह है कि यह स्रोत कोड के केवल टुकड़ों को डीपार्स कर सकता है और किसी दिए गए बाइटकोड ऑफ़सेट के आसपास स्रोत-कोड जानकारी दे सकता है।
मैं ट्री फ्रैगमेंट का उपयोग अपने trepan_ डिबगर्स_ में रन टाइम पर कोड के टुकड़ों को डीपार्स करने के लिए करता हूँ। उसके लिए, बाइटकोड ऑफ़सेट रिकॉर्ड किए जाते हैं और स्रोत कोड के टुकड़ों से जुड़े होते हैं। यह उद्देश्य, मूल आशय के अनुकूल होने के बावजूद, थोड़ा अलग है। अधिक जानकारी के लिए this_ देखें।
एक निर्देश ऑफ़सेट दिए जाने पर Python फ्रैगमेंट डीपार्सिंग, स्टैक ट्रेस दिखाने में उपयोगी है और इसे किसी भी प्रोग्राम में शामिल किया जा सकता है जो रनटाइम पर सिर्फ एक लाइन नंबर से अधिक विस्तार में एक स्थान दिखाना चाहता है। यह कोड तब भी उपयोग किया जा सकता है जब स्रोत कोड जानकारी मौजूद न हो और केवल बाइटकोड हो। फिर से, मेरे डिबगर्स इसका उपयोग करते हैं।
पहले (और अब भी) कई decompyle, uncompyle, uncompyle2, uncompyle3 फोर्क थे। उनमें से कई मूलतः एक ही कोड बेस से आते हैं, और (लगभग?) सभी अब सक्रिय रूप से बनाए नहीं रखे जाते हैं। एक Python 1.5-2.3 को डीकंपाइल करने में वास्तव में अच्छा था, दूसरा Python 2.7 में वास्तव में अच्छा है, लेकिन केवल वही। दूसरा केवल Python 3.2 को संभालता है; दूसरे ने उसे पैच किया और केवल 3.3 को संभाला। आप विचार समझ गए होंगे। यह कोड इन सभी फोर्क्स को एक साथ लाता है और आगे बढ़ता है। इस कोड बेस में उन पुराने फोर्क्स की तुलना में गंभीर रीफैक्टरिंग और सफाई है। decompyle3_ में और भी अधिक प्रयोगात्मक रीफैक्टरिंग चल रही है।
यह स्पष्ट रूप से सभी Python संस्करणों में Python को डीकंपाइल करने में सर्वश्रेष्ठ प्रदर्शन करता है। और भले ही कोई अन्य प्रोजेक्ट हो जो केवल Python संस्करणों के एक उपसमुच्चय के लिए डीकंपाइलेशन प्रदान करता हो, हम आम तौर पर उनके लिए भी स्पष्ट रूप से बेहतर करते हैं।
हम कैसे बता सकते हैं? उस Python संस्करण के साथ वितरित Python बाइटकोड लेकर और उसे डीकंपाइल करके। उन लोगों में से जो सफलतापूर्वक डीकंपाइल करते हैं, हम यह सुनिश्चित कर सकते हैं कि परिणामी प्रोग्राम सिंटैक्टिक रूप से सही हैं, उस बाइटकोड संस्करण के लिए Python इंटरप्रेटर चलाकर। अंत में, ऐसे मामलों में जहाँ प्रोग्राम में स्वयं के लिए एक परीक्षण है, हम डीकंपाइल कोड पर जाँच चला सकते हैं।
हम बग खोजने के लिए स्वचालित प्रक्रियाओं का उपयोग करते हैं। अन्य डीकंपाइलरों के इश्यू ट्रैकर्स में, आपको रास्ते में हमारे द्वारा पाए गए कई बग मिलेंगे। उनमें से बहुत कम अन्य डीकंपाइलरों में ठीक किए गए हैं।
गिट रिपॉजिटरी में कोड Python 2.4 से नवीनतम Python संस्करण तक चलाया जा सकता है, Python 3.0 से 3.2 को छोड़कर। यदि ऐसा करने की इच्छा है, तो स्वयंसेवकों का स्वागत है जो इन कमियों को दूर करें।
हालाँकि, यह ऐसा करने का तरीका लगातार Python संस्करणों को गिट ब्रांचों में अलग करके है:
master Python 3.11 और उससे ऊपर (poetry install और नए Python मुहावरों का उपयोग करता है) python-3.6-to-3.10 Python 3.6 से 3.10 (नए f-strings, अधिक आधुनिक मुहावरे, और अधिक आधुनिक Type annotations का उपयोग करता है) python-3.3-to-3.5 Python 3.3 से 3.5 (सामान्य Python 3) python-3.0-to-3.2 Python 3.0 से 3.2 (प्रारंभिक Python 3; 3.0 कुछ क्षेत्रों में Python 2.6 के करीब था, Python 2.7 से अधिक) python-2.4-to-2.7 Python 2.4 से 2.7 (सामान्य Python 2)
PyPy संस्करण 2.4 से ऊपर भी काम करता है।
यह जो बाइटकोड फ़ाइलें पढ़ सकता है, उनका परीक्षण Python बाइटकोड पर संस्करण 1.4, 2.1-2.7, और 3.0-3.8 और बाद के PyPy संस्करणों से किया गया है।
हाल के Python रिलीज़ (Python 3.11+) के लिए, आप PyPI से uncompyle6 नाम का उपयोग करके स्थापित कर सकते हैं::
pip install uncompyle6
Python 3.11 से पहले के रिलीज़ के लिए, PyPI का उपयोग करके स्थापित न करें, बल्कि GitHub Releases section में एक फ़ाइल का उपयोग करके स्थापित करें। पुराने Python में easy_install <https://python101.pythonlibrary.org/chapter29_pip.html#using-easy-install>_ का उपयोग होता था। लेकिन यह अब PyPi या नए Python संस्करणों पर समर्थित नहीं है। और इसके विपरीत, poetry या pip, (नए तरीके) पुराने Python पर समर्थित नहीं हैं।
यदि आप जिस Python संस्करण पर uncompyle6 चला रहे हैं, वह Python 2.4 से 2.7 के बीच है, तो uncompyle6_24-x.y.z.tar.gz नामक टारबॉल का उपयोग करें।
यदि आप जिस Python संस्करण पर uncompyle6 चला रहे हैं, वह Python 3.0 से 3.2 के बीच है, तो uncompyle6_30-x.y.z.tar.gz नामक टारबॉल का उपयोग करें।
यदि आप जिस Python संस्करण पर uncompyle6 चला रहे हैं, वह Python 3.3 से 3.5 के बीच है, तो uncompyle6_33-x.y.z.tar.gz नामक टारबॉल का उपयोग करें।
यदि आप जिस Python संस्करण पर uncompyle6 चला रहे हैं, वह Python 3.6 से 3.11 के बीच है, तो uncompyle6_36-x.y.z.tar.gz नामक टारबॉल का उपयोग करें।
यदि आप जिस Python संस्करण पर uncompyle6 चला रहे हैं, वह 3.11 या बाद का है, तो uncompyle6-x.y.z.tar.gz नामक टारबॉल का उपयोग करें।
आप अंडे या व्हील भी आज़मा सकते हैं जिनका समान संस्करण पदनाम है, उदाहरण के लिए, Python 3.9 स्थापना के लिए uncompyle6-x.y.z-py39-none-any.whl। *हालाँकि, ध्यान दें कि पदनाम के बिना संस्करण का अर्थ है Python 3.11 या उससे अधिक।
इसी प्रकार, बिना _xx वाला टारबॉल केवल Python 3.11 या उससे अधिक पर काम करता है।
गिट ब्रांच का उपयोग करने का तर्क ++++++++++++++++++++++++++++++++
वर्तमान में एक Python स्रोत कोड होना संभव नहीं है (यदि अव्यावहारिक नहीं है) जो इतनी जटिलता और इतनी सुविधाओं के साथ Python 2.7 और Python 3.13+ दोनों पर चल सके। भाषाएँ इतनी अलग हो गई हैं, और पैकेजिंग बहुत अलग है। वास्तव में, Python 3.11+ के लिए पैकेजिंग प्रथा Python 2.7 (और उससे पहले Python 2.4 तक) के साथ असंगत है, जो "easy_install" का पक्षधर था।
स्रोत पाठ से स्थापना ++++++++++++++++++++++
स्रोत कोड से स्थापित करने के लिए, सुनिश्चित करें कि आपके पास सही गिट शाखा है। गिट शाखा नामों के लिए आवश्यकताएँ अनुभाग देखें।
सही शाखा सेट करने के बाद::
$ pip install -e . # स्रोत ट्री से चलाने के लिए सेट करें
एक GNU Makefile भी प्रदान किया गया है, इसलिए :code:make install (संभवतः रूट या sudo के रूप में) उपरोक्त चरणों को करेगा।
::
make check
एक GNU makefile को सही कमांड सेट अप करने और चलाने, और परीक्षणों को सबसे तेज़ से सबसे धीमी गति से चलाने के लिए जोड़ा गया है।
यदि आपके पास remake_ स्थापित है, तो आप :code:remake --tasks के माध्यम से परीक्षणों सहित सभी कार्यों की सूची देख सकते हैं।
चलाएँ
::
$ uncompyle6 compiled-python-file-pyc-or-pyo
उपयोग सहायता के लिए:
::
$ uncompyle6 -h
Python के पुराने संस्करणों में, बाइटकोड को डीकंपाइल करके और फिर उस बाइटकोड संस्करण के लिए Python इंटरप्रेटर का उपयोग करके संकलित करके सत्यापित करना संभव था। ऐसा करने के बाद, उत्पादित बाइटकोड की तुलना मूल बाइटकोड से की जा सकती थी। हालाँकि, जैसे-जैसे Python का कोड जनरेशन बेहतर होता गया, यह अब संभव नहीं रहा।
यदि आप डीकंपाइलेशन प्रक्रिया की शुद्धता का Python सिंटैक्स सत्यापन चाहते हैं, तो :code:--syntax-verify विकल्प जोड़ें। हालाँकि, चूंकि Python सिंटैक्स बदलता है। आपको इस विकल्प का उपयोग करना चाहिए यदि बाइटकोड उस Python इंटरप्रेटर के लिए सही बाइटकोड है जो सिंटैक्स की जाँच करेगा।
आप परिणामों की तुलना uncompyle6 के किसी अन्य संस्करण से भी कर सकते हैं, क्योंकि कभी-कभी विशिष्ट बाइटकोड को डीकंपाइल करने में नियमन होते हैं, क्योंकि समग्र गुणवत्ता में सुधार होता है।