अद्यतन: सैंड्री कारणों से मैंने क्रॉस-पायथन-संस्करण असेंबलर लिखना शुरू कर दिया है। https://github.com/rocky/python-xasm देखें यह अभी भी बहुत शुरुआती बीटा में है।
जहाँ तक मुझे पता के रूप में वहाँ कोई वर्तमान में बनाए रखा अजगर कोडांतरक है। PEAK's Bytecode Disassembler पायथन 2.6 के लिए विकसित किया गया था, और बाद में प्रारंभिक पायथन 2.7 का समर्थन करने के लिए संशोधित किया गया।
यह documentation से बहुत अच्छा है। लेकिन यह अन्य पीक पुस्तकालयों पर निर्भर करता है जो समस्याग्रस्त हो सकते हैं।
मैं आपको पूरा करने के लिए एक उदाहरण देने के लिए पूरे उदाहरण के माध्यम से जाऊंगा। यह सुंदर नहीं है, लेकिन फिर आपको इसकी उम्मीद करनी चाहिए।
मूल रूप से बाइटकोड को संशोधित करने के बाद, आपको एक नया types.CodeType
ऑब्जेक्ट बनाना होगा। आपको एक नया कारण चाहिए क्योंकि कोड प्रकार में कई ऑब्जेक्ट्स, अच्छे कारण के लिए, आप नहीं बदल सकते हैं। उदाहरण के लिए दुभाषिया में इन ऑब्जेक्ट मानों में से कुछ कैश हो सकते हैं।
कोड बनाने के बाद, आप इसे ऐसे कोडों में उपयोग कर सकते हैं जो कोड प्रकार का उपयोग करते हैं जिसका उपयोग exec
या eval
में किया जा सकता है।
या आप इसे एक बाइटकोड फ़ाइल में लिख सकते हैं। हां कोड प्रारूप Python 2 और पायथन 3 के बीच बदल गया है और वैसे भी अनुकूलन और बाइटकोड है। वास्तव में, पायथन 3.6 में वे शब्द कोड बाइटकोड नहीं होंगे।
3 0 LOAD_CONST 1 (8)
3 STORE_FAST 0 (a)
4 6 LOAD_CONST 2 (0)
9 STORE_FAST 0 (a)
5 12 LOAD_FAST 0 (a)
15 RETURN_VALUE
==============================
3 0 LOAD_CONST 2 (0)
3 STORE_FAST 0 (a)
4 6 LOAD_FAST 0 (a)
9 RETURN_VALUE
==============================
('Result is', 0)
3 0 LOAD_CONST 2 (10)
3 STORE_FAST 0 (a)
4 6 LOAD_FAST 0 (a)
9 RETURN_VALUE
==============================
('Result is now', 10)
सूचना है कि लाइन नंबर नहीं है:
a = """
def fact():
a = 8
a = 0
return a
"""
c = compile(a, '<string>', 'exec')
fn_code = c.co_consts[0] # Pick up the function code from the main code
from dis import dis
dis(fn_code)
print("=" * 30)
x = fn_code.co_code[6:16] # modify bytecode
import types
opt_fn_code = types.CodeType(fn_code.co_argcount,
# c.co_kwonlyargcount, Add this in Python3
fn_code.co_nlocals,
fn_code.co_stacksize,
fn_code.co_flags,
x, # fn_code.co_code: this you changed
fn_code.co_consts,
fn_code.co_names,
fn_code.co_varnames,
fn_code.co_filename,
fn_code.co_name,
fn_code.co_firstlineno,
fn_code.co_lnotab, # In general, You should adjust this
fn_code.co_freevars,
fn_code.co_cellvars)
dis(opt_fn_code)
print("=" * 30)
print("Result is", eval(opt_fn_code))
# Now let's change the value of what's returned
co_consts = list(opt_fn_code.co_consts)
co_consts[-1] = 10
opt_fn_code = types.CodeType(fn_code.co_argcount,
# c.co_kwonlyargcount, Add this in Python3
fn_code.co_nlocals,
fn_code.co_stacksize,
fn_code.co_flags,
x, # fn_code.co_code: this you changed
tuple(co_consts), # this is now changed too
fn_code.co_names,
fn_code.co_varnames,
fn_code.co_filename,
fn_code.co_name,
fn_code.co_firstlineno,
fn_code.co_lnotab, # In general, You should adjust this
fn_code.co_freevars,
fn_code.co_cellvars)
dis(opt_fn_code)
print("=" * 30)
print("Result is now", eval(opt_fn_code))
जब मैं इस यहाँ भाग गया मैं क्या मिल गया है:
तो यहाँ आप अपने उदाहरण के लिए क्या करना होगा क्या है हालांकि मैंने कोड में दो पंक्तियों को हटा दिया। ऐसा इसलिए है क्योंकि मैंने fn_code.co_lnotab
अपडेट नहीं किया था।
यदि आप अब से एक पायथन बाइटकोड फ़ाइल लिखना चाहते हैं। आपको यह होता क्या है:
co_consts = list(c.co_consts)
co_consts[0] = opt_fn_code
c1 = types.CodeType(c.co_argcount,
# c.co_kwonlyargcount, Add this in Python3
c.co_nlocals,
c.co_stacksize,
c.co_flags,
c.co_code,
tuple(co_consts),
c.co_names,
c.co_varnames,
c.co_filename,
c.co_name,
c.co_firstlineno,
c.co_lnotab, # In general, You should adjust this
c.co_freevars,
c.co_cellvars)
from struct import pack
with open('/tmp/testing.pyc', 'w') as fp:
fp.write(pack('Hcc', 62211, '\r', '\n')) # Python 2.7 magic number
import time
fp.write(pack('I', int(time.time())))
# In Python 3 you need to write out the size mod 2**32 here
import marshal
fp.write(marshal.dumps(c1))
लिख ऊपर बॉयलरप्लेट बाईटकोड, मैं करने के लिए कहा जाता है xdiswrite_python_file() एक नियमित जोड़ दिया है आसान बनाने के लिए।
अब परिणामों की जांच करने के लिए:
$ uncompyle6 /tmp/testing.pyc
# uncompyle6 version 2.9.2
# Python bytecode 2.7 (62211)
# Disassembled from: Python 2.7.12 (default, Jul 26 2016, 22:53:31)
# [GCC 5.4.0 20160609]
# Embedded file name: <string>
# Compiled at: 2016-10-18 05:52:13
def fact():
a = 0
# okay decompiling /tmp/testing.pyc
$ pydisasm /tmp/testing.pyc
# pydisasm version 3.1.0
# Python bytecode 2.7 (62211) disassembled from Python 2.7
# Timestamp in code: 2016-10-18 05:52:13
# Method Name: <module>
# Filename: <string>
# Argument count: 0
# Number of locals: 0
# Stack size: 1
# Flags: 0x00000040 (NOFREE)
# Constants:
# 0: <code object fact at 0x7f815843e4b0, file "<string>", line 2>
# 1: None
# Names:
# 0: fact
2 0 LOAD_CONST 0 (<code object fact at 0x7f815843e4b0, file "<string>", line 2>)
3 MAKE_FUNCTION 0
6 STORE_NAME 0 (fact)
9 LOAD_CONST 1 (None)
12 RETURN_VALUE
# Method Name: fact
# Filename: <string>
# Argument count: 0
# Number of locals: 1
# Stack size: 1
# Flags: 0x00000043 (NOFREE | NEWLOCALS | OPTIMIZED)
# Constants:
# 0: None
# 1: 8
# 2: 10
# Local variables:
# 0: a
3 0 LOAD_CONST 2 (10)
3 STORE_FAST 0 (a)
4 6 LOAD_CONST 0 (None)
9 RETURN_VALUE
$
अनुकूलन के लिए एक वैकल्पिक दृष्टिकोण Abstract Syntax Tree स्तर (एएसटी) में अनुकूलन करने के लिए है। हालांकि मुझे यकीन नहीं है कि आप इसे सीधे निष्पादित कर सकते हैं। कुछ मॉड्यूल दिनचर्या ऐसा सुझाव देते हैं कि आप कर सकते हैं। या आप एएसटी से बाइटकोड फ़ाइल कैसे उत्पन्न करेंगे। तो मुझे लगता है कि आप इसे वापस पायथन स्रोत के रूप में लिखते हैं।
मुझे उत्सुकता है कि आप ऐसा क्यों करेंगे, आपका उपयोग केस क्या है? – shuttle87
पायथन बाइटकोड को एक कार्यान्वयन विस्तार माना जाता है और संस्करण से संस्करण और दुभाषिया को दुभाषिया में बदल सकता है। दुभाषिया स्रोत को छोड़कर कोई दस्तावेज नहीं है। क्या आप वास्तव में इसे करना चाहते हैं? – Antimony
@ शटल 87, मैं स्क्रिप्ट के साथ एक गेम इंजन लिख रहा हूं जिसे मैं पाइथन में लिखने की उम्मीद कर रहा हूं, लेकिन मैं स्क्रिप्ट्स बाइटकोड पर कुछ ऑप्टिमाइज़ेशन चलाने के लिए चाहता हूं जो कमजोर बोलने से पहले ही ज्ञात नहीं होंगे (हालांकि मूल संरचना जाना जाता है क्योंकि वे सभी एक सामान्य आधार वर्ग साझा करते हैं)। मेरे पास अन्य सभी घटक काम कर रहे हैं, बस इस प्रयोज्य बाइटकोड को उपयोग करने योग्य फ़ंक्शन में अंतिम बाधा है। –