为什么C程序需要反编译器,但python程序不需要?
如果我编写一个python脚本,任何人都可以简单地将一个编辑器指向它并阅读它。但对于使用C语言编写的程序,必须使用反编译器和十六进制表等。这是为什么?我的意思是我根本无法打开Safari浏览器并查看其代码。为什么C程序需要反编译器,但python程序不需要?
注意:作者拒绝在这个主题的深厚专业知识。有些断言可能不正确。
Python实际上被编译成字节码,这是python解释器运行的东西。无论何时使用Python模块,Python都会生成一个.pyc
文件,其名称对应于该模块。这相当于编译C文件时生成的.o
文件。
所以,如果你想要的东西拆开,将.pyc
文件将是吧:)
了Python经过时编译一个模块是非常类似于gcc
或其他C编译器C源代码的代码做的过程。主要区别在于它作为文件执行的一部分透明地进行。它也是可选的:在运行非模块(即最终用户脚本)时,Python只会解释代码而不是先编译它。
所以真的你的问题是“为什么python程序是以源代码而不是以编译模块的形式发布的?”换句话说,“为什么C应用程序是作为编译的二进制文件而不是源代码来分发的?”
它曾经是非常普遍的C应用程序作为源代码分发。这是在操作系统及其各种子实体(即Linux发行版)变得更加成熟之前回来的。一些发行版,例如gentoo,仍然将应用程序分发为源代码。应用程序有点尖端或模糊,仍然作为它们所针对的所有平台的源代码分发。
原因是兼容性和依赖性。您可以在Mac上运行预编译的二进制Safari,或者在Ubuntu Linux上运行Firefox,原因是它专门为该操作系统,体系结构(例如x86_64)和库集合构建。
不幸的是,编译大型应用程序相当缓慢,每次应用程序更新时都需要至少部分重做。因此二元分布的动机。
那么,为什么不创建一个Python的二进制分布?首先,正如Aaron mentions,模块需要重新编译每个新版本的Python字节码。但这与重建C应用程序以链接动态库的新版本类似 - 在这种意义上,Python库与C库类似。
真正的原因是Python编译比C编译快得多。我认为这部分是由于该语言的动态性质,也因为它不像编译过程那么彻底。这有其折衷:特别是,Python应用程序的运行速度远远超过C程序,因为Python必须将编译的字节码解释为处理器的指令,而C应用程序已经包含这些指令。
所有人都说,有一个名为py2exe的程序,它将采用Python模块和发行版并构建预编译的Windows可执行文件,其中包括模块及其依赖项的逻辑(包括Python本身)。我想这一点是为了避免强制人们在他们的Windows系统上安装Python来运行你的应用程序。在Linux下,或者我认为甚至OS/X,Python通常已经安装,所以预编译并不是真的必要。 Linux系统也有超级包管理器,如果它们尚未安装,它们将透明地安装诸如Python之类的依赖项。
Python是一种脚本语言,通过中间人在虚拟机中运行。 C是一种编译语言,将代码编译为二进制代码,计算机可以在没有所需的额外东西的情况下运行该代码。
是否有可能编译python到一个可执行的二进制文件,然后简单地分发? – Ali 2010-10-06 04:33:23
@Ali:不,没有合理的方式去做,不要相信别的。 – 2010-10-06 04:45:31
因为C代码符合对象(机器)代码,并且python代码被编译为中间字节代码。我不确定你是否指的是python的字节码 - 你必须引用可直接执行的源文件本身(隐藏你的字节码!)。 C需要编译和链接。
- Python脚本只有在运行时才被解析并转换为二进制文件 - 即它们是文本文件,您可以使用编辑器读取它们。
- C代码被编译并链接到一个可执行的二进制文件,然后才能运行。通常,只有这个可执行的二进制文件是分布式的 - 因此你需要一个反编译器。你可以随时查看源代码,如果你有权访问它。
您无法打开并阅读实际为python运行的代码。尝试
import dis
def foo():
for i in range(100):
print i
print dis.dis(foo)
这会显示foo
程序的(人类可读的)bytcode。等价地,您可以保存该文件并从交互式Python解释器中导入它。这将创建一个.pyc
文件,其脚本具有相同的基本名称。用十六进制编辑器打开它,然后查看实际的python字节码。
不同之处在于,python在不同版本之间更改了字节码,因此您需要为每个版本的Python分发不同版本的二进制版本。这将是一个痛苦。
随着C,它被编译为本地代码,所以字节代码更加稳定,使得只有二进制版本成为可能。
这是一个很大的话题。你应该看看你当地友好的计算机科学课程,你会发现很多有关这个主题的伟大的东西。
简短的答案是Python是一种“解释”语言,这意味着它需要一个机器语言程序(python解释器)来运行python程序,并添加一个间接层。 C或C++是不同的。它们直接编译为机器码,可直接在处理器上运行。
然而,这里有很多额外的伏都教。从技术上讲,Python被编译为一个字节码,而现代解释器的编译越来越多,所以编译和解释代码之间的界限越来越模糊。
是的,你可以 - 它被称为反汇编,并允许你很好地看看Safari的代码。问题是,C和其他语言一样,编译为本地代码,即CPU可以“理解”并执行的代码。
或多或少显然,CPU指令集中的抽象级别远远低于像Python这样的高级语言。CPU指令不关心“下载该URI”,而是更多地“检查该位是否设置在硬件寄存器中”。
因此,总之,在本机应用程序中出现的复杂程度在查看机器代码时要高得多,因此很多人根本无法理解那里发生的事情,很难获得大的图片。随着经验和时间的掌握,人们可能会一直这样做,扭转应用和所有情况。
然后可以编译python到一个可执行的二进制文件,然后简单地分发它? – Ali 2010-10-06 04:32:59
Python脚本与查看用英语(或他理解的语言)编写的待办事项列表的人类似。这个人必须完成所有的工作,每次都要完成这些事情。如果这个人不是每次都独自完成这些步骤,而是创建并编程一个能够一次又一次地执行这些步骤的机器人(并且可能比他更快),那么这个机器人就类似于C程序。
python情况下的人称为“解释器”,在C情况下称为“编译器”,C机器人称为编译程序/可执行文件。
当您查看python程序源代码时,您会看到待办事项列表。在机器人的情况下,你会看到齿轮,电机和电池等,这些与待办事项列表看起来有很大不同。如果你能够掌握C的“待办事项”列表,它看起来有点像Python代码,只是用不同的语言。
编译Python脚本。它们只是为仅存在于软件中的机器编译的。 Python的“解释器”是该机器的一个模拟器,它具有一个嵌入式编译器,并将其移植到顶层,以便将该脚本编译为该虚拟机器的目标代码格式。 – 2010-10-06 04:44:18
非常感谢 - 我知道那些细节。假设问题提出者的代谢率适中,我可以很容易地进行消化。 – Rajan 2010-10-06 05:23:58
并非所有的C程序都需要反编译器。有很多C代码以源代码形式分发。如果分发为字节码(.pyc文件),一些Python程序做需要反编译器。
但是,就您的假设有效而言,这是因为C是compiled language而Python是interpreted language。
python不仅仅是java的解释性语言。它在虚拟机上运行。 – aaronasterling 2010-10-06 04:28:35
在你问到的几个注释中:“是否可以将python编译为可执行的二进制文件,然后简单地分发它?
从理论的角度来看,毫无疑问答案是肯定的 - 一个Python程序可以被编译成完全编译的机器代码,并且可以作为完全编译的机器代码分发。
从实践的角度来看,它有更多的问题。有一些东西,如Unladen Swallow,Psyco,Shed Skin和PyPy,你可能想知道。
Unladen Swallow主要是在制作的Python运行更快的尝试,但部分计划这样做,包括使用LLVM其后端。 LLVM可以(除其他外)生成本机机器码输出。 Unladen Swallow的最后几个版本使用LLVM进行本地代码生成,但是 1)网站上的最新更新是从2009年底开始的,2)该版本的发行说明说:“Unladen Swallow团队并不建议广泛采用2009Q3版本。“
Psyco作为一个基本上可以进行JIT编译的Python插件,所以即使它可以加快执行速度(在某些情况下相当多),但它不会生成可分发的机器代码可执行文件。总之,虽然它与你想要的类似,但并不打算按照你的要求去做。
Shed Skin Python-to-C++生成C++作为其输出,然后编译C++并(可能)分发结果。 Shedskin目前在0.5版本 - 即没有人声称它是一个完成的,发布的产品。另一方面,开发正在进行中,每个版本似乎都包含相当大的改进。
PyPy是用Python编写的Python实现。他们的意图是允许代码生成“插入”而不影响其余的实现 - 但他们目前支持4种不同的代码生成模型,我不相信它们中的任何一个会生成本地机器代码直接在硬件上运行。
底线:工作已经完成,目前正在与做你问什么的意图完成,但至少据我所知,这不是真的什么我可以合理建议作为成品,你现在真的可以依靠做这项工作了。主要重点在于执行速度,而不是生成独立的可执行文件。
G-WAN在运行时执行ANSI C脚本 - 就像Python脚本一样。
这可以是服务器端脚本(使用G-WAN作为Web服务器)或任何通用C程序,您可以链接任何现有的库。
哦,和G-WAN C脚本比Python,PHP或Java快得多......
这与此有关吗? – NullUserException 2010-10-06 15:28:09
应该有年龄段的标签。 – Yehonatan 2010-10-06 04:47:09
@Yehonatan:我认为收集所有关于编程的新手问题的标签是一个好主意 – pyfunc 2010-10-06 05:03:49
@pyfunc:[管理层不同意。](http://blog.stackoverflow.com/2010/08/the-death-of-meta -tags /) – intuited 2010-10-06 05:18:29