Python - 浅谈Python的编译与反编译
1 - Python编译过程涉及的文件
py
源代码文件,由python.exe解释,可在控制台下运行,可用文本编辑器进行编辑;
pyc
源代码文件经过编译后生成的二进制文件,无法用文本编辑器进行编辑;
执行一个.py文件后,并不会自动生成对应的.pyc文件,需要指定触发Python来创建pyc文件;
- pyc是由py文件经过编译后生成的二进制字节码(byte code)文件;
- pyc文件的加载速度比py文件快;
- pyc文件是一种跨平台的字节码,由python的虚拟机来执行;
- pyc文件的内容跟python版本相关,不同的python版本编译生成不同的pyc文件,只能在相同版本环境下执行;
pyo
源代码文件经过优化编译后生成的文件,无法用文本编辑器进行编辑;
Python3.5之后,不再使用.pyo文件名,而是使用类似“xxx.opt-n.pyc的文件名;
pyd
是python的动态链接库;
动态链接库(DLL)文件是一种可执行文件,允许程序共享执行特殊任务所必需的代码和其他资源;
pyd文件虽然是作为python的动态模块,但实质上还是DLL文件,只是后缀改为pyd;
一般是用C、C++、D语言按照一定的格式编写;
参考信息:https://docs.python.org/3/faq/windows.html?highlight=pyd#is-a-pyd-file-the-same-as-a-dll
pyz
从Python 3.5开始,定义了.pyz和.pyzw分别作为“Python Zip应用”和“Windows下Python Zip应用”的扩展名。
新增了内置zipapp模块来进行简单的管理,可以用Zip打包Python程序到一个可执行.pyz文件。
- zipapp — Manage executable python zip archives
- https://docs.python.org/3/library/zipapp.html
详细内容请见PEP441(https://www.python.org/dev/peps/pep-0441/)
2 - 生成pyc文件
执行一个.py文件后,并不会自动生成对应的.pyc文件,需要指定触发Python来创建pyc文件。
可以利用Python的import机制创建pyc文件:
- 内置的py_compile模块可以把py文件编译为pyc或pyo文件;
- 内置的compileall模块可以把整个目录中的py文件编译为pyc或pyo文件;
生成pyc文件的过程:
Python在执行import语句时(例如“import abc”),将会到已设定的path中寻找abc.pyc或abc.dll文件。
如果只是发现了abc.py,那么Python会首先将abc.py编译成相应的PyCodeObject中间结果,然后创建abc.pyc文件,并将中间结果写入该文件。
然后,Python会import这个abc.pyc文件,实际上也就是将abc.pyc文件中的PyCodeObject重新在内存中复制出来。
生成pyc文件的方法:
命令形式:
python -m py_compile file.py # 生成单个pyc文件
python -m py_compile /dir/{file1,file2}.py # 生成多个pyc文件
python -m compileall /dir/ # 生成目录下所有py文件对应的pyc文件
脚本形式:compile模块的compile函数
import py_compile # 相当于命令行中的“-m py_compile”
py_compile.compile('py file path')
脚本形式:compileall模块的compile_dir函数
import compileall
compileall.compile_dir("py files dir")
生成pyc文件示例:
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.py
anliven@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.py
anliven@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.pyc
3 - 生成pyo文件
与生成pyc文件类似,但要额外使用-O和-OO选项来生成pyo文件。
但在Python3.5之后,不再使用.pyo文件名,而是生成文件名类似“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文件
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.py
anliven@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.pyo
4 - 运行pyc或pyo文件
运行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 !
运行pyo文件
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.pyo
anliven@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进行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 uncompyle6
Downloading 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.pyc
anliven@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.py
anliven@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.pyc
anliven@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.pyc
anliven@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 --help
Usage:
uncompyle6 [OPTIONS]... [ FILE | DIR]...
uncompyle6 [--help | -h | --V | --version]
Examples:
uncompyle6 foo.pyc bar.pyc # decompile foo.pyc, bar.pyc to stdout
uncompyle6 -o . foo.pyc bar.pyc # decompile to ./foo.pyc_dis and ./bar.pyc_dis
uncompyle6 -o /tmp /usr/lib/python1.5 # decompile whole library
Options:
-o <path> output decompiled files to this path:
if multiple input files are decompiled, the common prefix
is 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_dis
uncompyle6 -o /tmp bla/fasel.pyc bar/foo.pyc
-> /tmp/bla/fasel.pyc_dis, /tmp/bar/foo.pyc_dis
uncompyle6 -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-code
and generated source output
--help show this message
Debugging 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)
6 - 其他Python反编译工具
Decompyle++
A Python Byte-code Disassembler/Decompiler
https://github.com/zrax/pycdc
Easy Python Decompiler
https://sourceforge.net/projects/easypythondecompiler/
Easy Python Decompiler is python bytecode decompiler, decompiles pyc & pyo files.
Python - 浅谈Python的编译与反编译的更多相关文章
- 浅谈Python在信息学竞赛中的运用及Python的基本用法
浅谈Python在信息学竞赛中的运用及Python的基本用法 前言 众所周知,Python是一种非常实用的语言.但是由于其运算时的低效和解释型编译,在信息学竞赛中并不用于完成算法程序.但正如LRJ在& ...
- 开发技术--浅谈Python函数
开发|浅谈Python函数 函数在实际使用中有很多不一样的小九九,我将从最基础的函数内容,延伸出函数的高级用法.此文非科普片~~ 前言 目前所有的文章思想格式都是:知识+情感. 知识:对于所有的知识点 ...
- python浅谈正则的常用方法
python浅谈正则的常用方法覆盖范围70%以上 上一次很多朋友写文字屏蔽说到要用正则表达,其实不是我不想用(我正则用得不是很多,看过我之前爬虫的都知道,我直接用BeautifulSoup的网页标签去 ...
- 浅谈Python时间模块
浅谈Python时间模块 今天简单总结了一下Python处理时间和日期方面的模块,主要就是datetime.time.calendar三个模块的使用.希望这篇文章对于学习Python的朋友们有所帮助 ...
- 浅谈python字符串存储形式
http://blog.csdn.net/zhonghuan1992 钟桓 2014年8月31日 浅谈python字符串存储形式 记录一下自己今的天发现疑问而且给出自己现有知识有的回答. 长话短说,用 ...
- 开发技术--浅谈python数据类型
开发|浅谈python数据类型 在回顾Python基础的时候,遇到最大的问题就是内容很多,而我的目的是回顾自己之前学习的内容,进行相应的总结,所以我就不玩基础了,很多在我实际生活中使用的东西,我会在文 ...
- 开发技术--浅谈python基础知识
开发|浅谈python基础知识 最近复习一些基础内容,故将Python的基础进行了总结.注意:这篇文章只列出来我觉得重点,并且需要记忆的知识. 前言 目前所有的文章思想格式都是:知识+情感. 知识:对 ...
- Java代码的编译与反编译那些事儿
原文:Java代码的编译与反编译那些事儿 编程语言 在介绍编译和反编译之前,我们先来简单介绍下编程语言(Programming Language).编程语言(Programming Language) ...
- Java| 编译和反编译
原文链接: http://www.yveshe.com/articles/2018/05/01/1525172129089.html 什么是编程语言? 在介绍编译和反编译之前,我们先来简单介绍下编程语 ...
随机推荐
- makefile入门-初步了解
自己开始学习makefile是由于VScode配置工程文件,看别人的配置不是很懂,于是决定入门学习下makefile. 先来说说makefile是做什么用的:makefile可以实现工程的自动化编译, ...
- span的title标签中的换行
var strs = data.flowSummary; strs=strs.replace(/燮r燮n/g," "); js的全局替换用/要替换的字符串/g span的titl ...
- java分布式电子商务云平台b2b b2c o2o需要准备哪些技术??
技术解决方案 开发语言: java.j2ee 数据库:mysql JDK支持版本: JDK1.6.JDK1.7.JDK1.8版本 核心技术:分布式.云服务.微服务.服务编排等. 核心架构: 使用Spr ...
- zz-人生感悟
1. 社交感想 首先来看一下聪明人和普通人的区别是什么? 普通人思考问题都是一步一步的来,由A推理出B,B推导到C,再推导出D,最后得出E,然而聪明人却可以由A直接推算到E. 这就像开车,普通人的是手 ...
- mac mysql5.7.17修改root初始密码(知道初始密码)
最近在mac上装个mysql可以说是麻烦死了,在这里就说说修改初始密码吧! 刚开始的时候不知道怎么修改,于是上网百度,网上几乎都是说要先执行命令mysqld_safe --skip-grant-tab ...
- ThinkPHP 3.2.3+ORACLE插入数据BUG修复及支持获取自增Id的上次记录
TP+ORACLE插入数据BUG修复以及获取自增Id支持getLastInsID方法 这些天在做Api接口时候,发现用TP操作Oracle数据库,发现查询修改删除都能执行, 但一旦执行插入操作老是报错 ...
- INTERVAL YEAR TO MONTH数据类型
INTERVAL YEAR TO MONTH数据类型 Oracle语法: INTERVAL 'integer [- integer]' {YEAR | MONTH} [(precision)][TO ...
- ajax用户是否存在
$(function(){ $("#username").blur(function(){ var usernameInput=$(this).val(); $.post( &qu ...
- JavaScript中的Undefined / Null 类型相关说明
1,综述: ※Undefined 和 Null是JavaScript中的两种数据类型(其他的类型还有:Boolean, String, Number, Object). ※Undefined类型只有一 ...
- REdis命令处理流程处理分析
分析版本:REdis-5.0.4. REdis命令处理流程可分解成三个独立的流程(不包括复制和持久化): 1) 接受连接请求流程: 2) 接收请求数据和处理请求流程,在这个过程并不会发送处理结果给Cl ...