浅谈Python的编译与反编译
1 - Python編譯過(guò)程涉及的文件
py
源代碼文件,由python.exe解釋,可在控制臺(tái)下運(yùn)行,可用文本編輯器進(jìn)行編輯;
pyc
源代碼文件經(jīng)過(guò)編譯后生成的二進(jìn)制文件,無(wú)法用文本編輯器進(jìn)行編輯;
執(zhí)行一個(gè).py文件后,并不會(huì)自動(dòng)生成對(duì)應(yīng)的.pyc文件,需要指定觸發(fā)Python來(lái)創(chuàng)建pyc文件;
- pyc是由py文件經(jīng)過(guò)編譯后生成的二進(jìn)制字節(jié)碼(byte code)文件;
- pyc文件的加載速度比py文件快;
- pyc文件是一種跨平臺(tái)的字節(jié)碼,由python的虛擬機(jī)來(lái)執(zhí)行;
- pyc文件的內(nèi)容跟python版本相關(guān),不同的python版本編譯生成不同的pyc文件,只能在相同版本環(huán)境下執(zhí)行;
pyo
源代碼文件經(jīng)過(guò)優(yōu)化編譯后生成的文件,無(wú)法用文本編輯器進(jìn)行編輯;
Python3.5之后,不再使用.pyo文件名,而是使用類(lèi)似“xxx.opt-n.pyc的文件名;
pyd
是python的動(dòng)態(tài)鏈接庫(kù);
動(dòng)態(tài)鏈接庫(kù)(DLL)文件是一種可執(zhí)行文件,允許程序共享執(zhí)行特殊任務(wù)所必需的代碼和其他資源;
pyd文件雖然是作為python的動(dòng)態(tài)模塊,但實(shí)質(zhì)上還是DLL文件,只是后綴改為pyd;
一般是用C、C++、D語(yǔ)言按照一定的格式編寫(xiě);
參考信息:https://docs.python.org/3/faq/windows.html?highlight=pyd#is-a-pyd-file-the-same-as-a-dll
pyz
從Python 3.5開(kāi)始,定義了.pyz和.pyzw分別作為“Python Zip應(yīng)用”和“Windows下Python Zip應(yīng)用”的擴(kuò)展名。
新增了內(nèi)置zipapp模塊來(lái)進(jìn)行簡(jiǎn)單的管理,可以用Zip打包Python程序到一個(gè)可執(zhí)行.pyz文件。
- zipapp — Manage executable python zip archives
- https://docs.python.org/3/library/zipapp.html
詳細(xì)內(nèi)容請(qǐng)見(jiàn)PEP441(https://www.python.org/dev/peps/pep-0441/)
2 - 生成pyc文件
執(zhí)行一個(gè).py文件后,并不會(huì)自動(dòng)生成對(duì)應(yīng)的.pyc文件,需要指定觸發(fā)Python來(lái)創(chuàng)建pyc文件。
可以利用Python的import機(jī)制創(chuàng)建pyc文件:
- 內(nèi)置的py_compile模塊可以把py文件編譯為pyc或pyo文件;
- 內(nèi)置的compileall模塊可以把整個(gè)目錄中的py文件編譯為pyc或pyo文件;
生成pyc文件的過(guò)程:
Python在執(zhí)行import語(yǔ)句時(shí)(例如“import abc”),將會(huì)到已設(shè)定的path中尋找abc.pyc或abc.dll文件。
如果只是發(fā)現(xiàn)了abc.py,那么Python會(huì)首先將abc.py編譯成相應(yīng)的PyCodeObject中間結(jié)果,然后創(chuàng)建abc.pyc文件,并將中間結(jié)果寫(xiě)入該文件。
然后,Python會(huì)import這個(gè)abc.pyc文件,實(shí)際上也就是將abc.pyc文件中的PyCodeObject重新在內(nèi)存中復(fù)制出來(lái)。
生成pyc文件的方法:
命令形式:
python -m py_compile file.py # 生成單個(gè)pyc文件 python -m py_compile /dir/{file1,file2}.py # 生成多個(gè)pyc文件 python -m compileall /dir/ # 生成目錄下所有py文件對(duì)應(yīng)的pyc文件腳本形式:compile模塊的compile函數(shù)
''' 遇到問(wèn)題沒(méi)人解答?小編創(chuàng)建了一個(gè)Python學(xué)習(xí)交流QQ群:579817333 尋找有志同道合的小伙伴,互幫互助,群里還有不錯(cuò)的視頻學(xué)習(xí)教程和PDF電子書(shū)! ''' import py_compile # 相當(dāng)于命令行中的“-m py_compile” py_compile.compile('py file path')腳本形式:compileall模塊的compile_dir函數(shù)
import compileall compileall.compile_dir("py files dir")生成pyc文件示例:
''' 遇到問(wèn)題沒(méi)人解答?小編創(chuàng)建了一個(gè)Python學(xué)習(xí)交流QQ群:579817333 尋找有志同道合的小伙伴,互幫互助,群里還有不錯(cuò)的視頻學(xué)習(xí)教程和PDF電子書(shū)! ''' anliven@DESKTOP-68OFQFP MINGW64 /d/Anliven/Anliven-Code/Test $ ls -l total 2 -rw-r--r-- 1 anliven 197121 50 3月 7 22:55 sample.py -rw-r--r-- 1 anliven 197121 49 3月 7 23:40 sample2.pyanliven@DESKTOP-68OFQFP MINGW64 /d/Anliven/Anliven-Code/Test $ cat sample.py # -*- coding: utf-8 -*- print("Hello Python !")anliven@DESKTOP-68OFQFP MINGW64 /d/Anliven/Anliven-Code/Test $ cat sample2.py # -*- coding: utf-8 -*- print("Hello World !")anliven@DESKTOP-68OFQFP MINGW64 /d/Anliven/Anliven-Code/Test $ python -m compileall ./ Listing './'... Compiling './sample.py'... Compiling './sample2.py'...anliven@DESKTOP-68OFQFP MINGW64 /d/Anliven/Anliven-Code/Test $ ls -l total 6 drwxr-xr-x 1 anliven 197121 0 3月 7 23:42 __pycache__/ -rw-r--r-- 1 anliven 197121 50 3月 7 22:55 sample.py -rw-r--r-- 1 anliven 197121 49 3月 7 23:40 sample2.pyanliven@DESKTOP-68OFQFP MINGW64 /d/Anliven/Anliven-Code/Test $ ls -l __pycache__/ total 2 -rw-r--r-- 1 anliven 197121 122 3月 7 23:41 sample.cpython-36.pyc -rw-r--r-- 1 anliven 197121 122 3月 7 23:41 sample2.cpython-36.pyc3 - 生成pyo文件
與生成pyc文件類(lèi)似,但要額外使用-O和-OO選項(xiàng)來(lái)生成pyo文件。
但在Python3.5之后,不再使用.pyo文件名,而是生成文件名類(lèi)似“xxx.opt-n.pyc的文件。
命令示例:
python -O -m py_compile file.py python -O -m py_compile /dir/{file1,file2}.py python -O -m compileall /dir/示例:python3.6生成pyo文件
''' 遇到問(wèn)題沒(méi)人解答?小編創(chuàng)建了一個(gè)Python學(xué)習(xí)交流QQ群:579817333 尋找有志同道合的小伙伴,互幫互助,群里還有不錯(cuò)的視頻學(xué)習(xí)教程和PDF電子書(shū)! ''' anliven@DESKTOP-68OFQFP MINGW64 /d/Anliven/Anliven-Code/Test $ python -O -m compileall ./ Listing './'... Compiling './sample.py'... Compiling './sample2.py'...anliven@DESKTOP-68OFQFP MINGW64 /d/Anliven/Anliven-Code/Test $ ls -l __pycache__/ total 4 -rw-r--r-- 1 anliven 197121 122 3月 7 23:42 sample.cpython-36.opt-1.pyc -rw-r--r-- 1 anliven 197121 122 3月 7 23:41 sample.cpython-36.pyc -rw-r--r-- 1 anliven 197121 122 3月 7 23:42 sample2.cpython-36.opt-1.pyc -rw-r--r-- 1 anliven 197121 122 3月 7 23:41 sample2.cpython-36.pyc示例:python2.7生成pyo文件
anliven@DESKTOP-68OFQFP MINGW64 /d/Anliven/Anliven-Code/Test $ ls -l total 6 drwxr-xr-x 1 anliven 197121 0 3月 7 23:42 __pycache__/ -rw-r--r-- 1 anliven 197121 50 3月 7 22:55 sample.py -rw-r--r-- 1 anliven 197121 49 3月 7 23:40 sample2.pyanliven@DESKTOP-68OFQFP MINGW64 /d/Anliven/Anliven-Code/Test $ py -2 -O -m compileall ./ Listing ./ ... Listing ./__pycache__ ... Compiling ./sample.py ... Compiling ./sample2.py ...anliven@DESKTOP-68OFQFP MINGW64 /d/Anliven/Anliven-Code/Test $ ls -l total 8 drwxr-xr-x 1 anliven 197121 0 3月 7 23:42 __pycache__/ -rw-r--r-- 1 anliven 197121 50 3月 7 22:55 sample.py -rw-r--r-- 1 anliven 197121 122 3月 7 23:45 sample.pyo -rw-r--r-- 1 anliven 197121 49 3月 7 23:40 sample2.py -rw-r--r-- 1 anliven 197121 122 3月 7 23:45 sample2.pyo4 - 運(yùn)行pyc或pyo文件
運(yùn)行pyc文件
anliven@DESKTOP-68OFQFP MINGW64 /d/Anliven/Anliven-Code/Test/__pycache__ $ python sample.cpython-36.pyc Hello Python !anliven@DESKTOP-68OFQFP MINGW64 /d/Anliven/Anliven-Code/Test/__pycache__ $ python sample2.cpython-36.pyc Hello World !anliven@DESKTOP-68OFQFP MINGW64 /d/Anliven/Anliven-Code/Test/__pycache__ $ python sample.cpython-36.opt-1.pyc Hello Python !anliven@DESKTOP-68OFQFP MINGW64 /d/Anliven/Anliven-Code/Test/__pycache__ $ python sample2.cpython-36.opt-1.pyc Hello World !運(yùn)行pyo文件
''' 遇到問(wèn)題沒(méi)人解答?小編創(chuàng)建了一個(gè)Python學(xué)習(xí)交流QQ群:579817333 尋找有志同道合的小伙伴,互幫互助,群里還有不錯(cuò)的視頻學(xué)習(xí)教程和PDF電子書(shū)! ''' anliven@DESKTOP-68OFQFP MINGW64 /d/Anliven/Anliven-Code/Test $ ls -l total 8 drwxr-xr-x 1 anliven 197121 0 3月 7 23:42 __pycache__/ -rw-r--r-- 1 anliven 197121 50 3月 7 22:55 sample.py -rw-r--r-- 1 anliven 197121 122 3月 7 23:45 sample.pyo -rw-r--r-- 1 anliven 197121 49 3月 7 23:40 sample2.py -rw-r--r-- 1 anliven 197121 122 3月 7 23:45 sample2.pyoanliven@DESKTOP-68OFQFP MINGW64 /d/Anliven/Anliven-Code/Test $ py -2 sample.pyo Hello Python !anliven@DESKTOP-68OFQFP MINGW64 /d/Anliven/Anliven-Code/Test $ py -2 sample2.pyo Hello World !5 - 利用uncompyle6進(jìn)行Python反編譯
uncompyle6
- Python cross-version byte-code decompiler
- PyPI:https://pypi.python.org/pypi/uncompyle6
- GitHub:https://github.com/rocky/python-uncompyle6
安裝uncompyle6
$ pip3 install --proxy="10.144.1.10:8080" uncompyle6 Collecting uncompyle6Downloading uncompyle6-3.0.0-py36-none-any.whl (195kB)100% |████████████████████████████████| 204kB 321kB/s Requirement already satisfied: six in c:\python36\lib\site-packages (from uncompyle6) Collecting spark-parser<1.9.0,>=1.8.5 (from uncompyle6)Downloading spark_parser-1.8.5-py36-none-any.whl Collecting xdis<3.7.0,>=3.6.9 (from uncompyle6)Downloading xdis-3.6.11-py36-none-any.whl (74kB)100% |████████████████████████████████| 81kB 153kB/s Collecting click (from spark-parser<1.9.0,>=1.8.5->uncompyle6)Using cached click-6.7-py2.py3-none-any.whl Installing collected packages: click, spark-parser, xdis, uncompyle6 Successfully installed click-6.7 spark-parser-1.8.5 uncompyle6-3.0.0 xdis-3.6.11$ pip3 show uncompyle6 Name: uncompyle6 Version: 3.0.0 Summary: Python cross-version byte-code decompiler Home-page: https://github.com/rocky/python-uncompyle6/ Author: Rocky Bernstein, Hartmut Goebel, John Aycock, and others Author-email: rb@dustyfeet.com License: MIT Location: c:\python36\lib\site-packages Requires: xdis, spark-parser, six示例:反編譯pyc文件
anliven@DESKTOP-68OFQFP MINGW64 /d/Anliven/Anliven-Code/Test/__pycache__ $ ls -l total 4 -rw-r--r-- 1 anliven 197121 122 3月 7 23:42 sample.cpython-36.opt-1.pyc -rw-r--r-- 1 anliven 197121 122 3月 7 23:41 sample.cpython-36.pyc -rw-r--r-- 1 anliven 197121 122 3月 7 23:42 sample2.cpython-36.opt-1.pyc -rw-r--r-- 1 anliven 197121 122 3月 7 23:41 sample2.cpython-36.pycanliven@DESKTOP-68OFQFP MINGW64 /d/Anliven/Anliven-Code/Test/__pycache__ $anliven@DESKTOP-68OFQFP MINGW64 /d/Anliven/Anliven-Code/Test/__pycache__ $ uncompyle6 sample.cpython-36.pyc > s1.pyanliven@DESKTOP-68OFQFP MINGW64 /d/Anliven/Anliven-Code/Test/__pycache__ $ ls -l total 5 -rw-r--r-- 1 anliven 197121 335 3月 8 00:01 s1.py -rw-r--r-- 1 anliven 197121 122 3月 7 23:42 sample.cpython-36.opt-1.pyc -rw-r--r-- 1 anliven 197121 122 3月 7 23:41 sample.cpython-36.pyc -rw-r--r-- 1 anliven 197121 122 3月 7 23:42 sample2.cpython-36.opt-1.pyc -rw-r--r-- 1 anliven 197121 122 3月 7 23:41 sample2.cpython-36.pycanliven@DESKTOP-68OFQFP MINGW64 /d/Anliven/Anliven-Code/Test/__pycache__ $ cat s1.py # uncompyle6 version 3.0.1 # Python bytecode 3.6 (3379) # Decompiled from: Python 3.6.2 (v3.6.2:5fd33b5, Jul 8 2017, 04:57:36) [MSC v.1900 64 bit (AMD64)] # Embedded file name: ./sample.py # Compiled at: 2018-03-07 22:55:30 # Size of source mod 2**32: 50 bytes print('Hello Python !') # okay decompiling sample.cpython-36.pycanliven@DESKTOP-68OFQFP MINGW64 /d/Anliven/Anliven-Code/Test/__pycache__ $示例:反編譯pyo文件
anliven@DESKTOP-68OFQFP MINGW64 /d/Anliven/Anliven-Code/Test $ ls -l total 8 drwxr-xr-x 1 anliven 197121 0 3月 8 00:01 __pycache__/ -rw-r--r-- 1 anliven 197121 50 3月 7 22:55 sample.py -rw-r--r-- 1 anliven 197121 122 3月 7 23:45 sample.pyo -rw-r--r-- 1 anliven 197121 49 3月 7 23:40 sample2.py -rw-r--r-- 1 anliven 197121 122 3月 7 23:45 sample2.pyo anliven@DESKTOP-68OFQFP MINGW64 /d/Anliven/Anliven-Code/Test $ anliven@DESKTOP-68OFQFP MINGW64 /d/Anliven/Anliven-Code/Test $ uncompyle6 sample2.pyo > s2.py anliven@DESKTOP-68OFQFP MINGW64 /d/Anliven/Anliven-Code/Test $ cat s2.py # uncompyle6 version 3.0.1 # Python bytecode 2.7 (62211) # Decompiled from: Python 3.6.2 (v3.6.2:5fd33b5, Jul 8 2017, 04:57:36) [MSC v.1900 64 bit (AMD64)] # Embedded file name: ./sample2.py # Compiled at: 2018-03-07 23:40:22 print 'Hello World !' # okay decompiling sample2.pyo anliven@DESKTOP-68OFQFP MINGW64 /d/Anliven/Anliven-Code/Test $uncompyle6的幫助信息
$ uncompyle6 --helpUsage:uncompyle6 [OPTIONS]... [ FILE | DIR]...uncompyle6 [--help | -h | --V | --version]Examples:uncompyle6 foo.pyc bar.pyc # decompile foo.pyc, bar.pyc to stdoutuncompyle6 -o . foo.pyc bar.pyc # decompile to ./foo.pyc_dis and ./bar.pyc_disuncompyle6 -o /tmp /usr/lib/python1.5 # decompile whole libraryOptions:-o <path> output decompiled files to this path:if multiple input files are decompiled, the common prefixis stripped from these names and the remainder appended to<path>uncompyle6 -o /tmp bla/fasel.pyc bla/foo.pyc-> /tmp/fasel.pyc_dis, /tmp/foo.pyc_disuncompyle6 -o /tmp bla/fasel.pyc bar/foo.pyc-> /tmp/bla/fasel.pyc_dis, /tmp/bar/foo.pyc_disuncompyle6 -o /tmp /usr/lib/python1.5-> /tmp/smtplib.pyc_dis ... /tmp/lib-tk/FixTk.pyc_dis-c <file> attempts a disassembly after compiling <file>-d print timestamps-p <integer> use <integer> number of processes-r recurse directories looking for .pyc and .pyo files--fragments use fragments deparser--verify compare generated source with input byte-code--verify-run compile generated source, run it and check exit code--weak-verify compile generated source--linemaps generated line number correspondencies between byte-codeand generated source output--help show this messageDebugging Options:--asm -a include byte-code (disables --verify)--grammar -g show matching grammar--tree -t include syntax tree (disables --verify)Extensions of generated files:'.pyc_dis' '.pyo_dis' successfully decompiled (and verified if --verify)+ '_unverified' successfully decompile but --verify failed+ '_failed' decompile failed (contact author for enhancement)總結(jié)
以上是生活随笔為你收集整理的浅谈Python的编译与反编译的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: python logging模块写入中文
- 下一篇: Python属性简介__name__