如果我编写一个python脚本,任何人都可以简单地将编辑器指向它并阅读它。但对于用C编写的编程,必须使用反编译器和十六进制表等。这是为什么?我的意思是我根本无法打开Safari网络浏览器并查看其代码。
答案 0 :(得分:12)
注意:作者否认在这个主题上有深厚的专业知识。有些断言可能不正确。
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等依赖项。
答案 1 :(得分:10)
Python是一种脚本语言,通过interpeter在虚拟机中运行。 C是一种编译语言,代码编译为二进制代码,计算机可以在没有Python需要的额外内容的情况下运行。
答案 2 :(得分:5)
这是一个很大的话题。你应该看一下你当地友好的计算机科学课程,你会在那里找到很多关于这个主题的好东西。
简短的回答是Python是一种“解释”语言,这意味着它需要一个机器语言程序(python解释器)来运行python程序,添加一层间接。 C或C ++是不同的。它们直接编译为机器代码,直接在您的处理器上运行。
然而,这里还有很多额外的伏都教。从技术上讲,Python被编译为字节码,现代解释器会进行越来越多的“及时”编译,因此编译代码和解释代码之间的界限越来越模糊。
答案 3 :(得分:3)
在几条评论中你问:“然后可以将python编译成可执行的二进制文件,然后简单地分发它吗?”
从理论的角度来看,毫无疑问答案是肯定的 - 可以将Python程序编译为完整编译的机器代码并进行分发。
从实际的角度来看,它可以提出更多问题。你可能想知道一些像Unladen Swallow,Psyco,Shed Skin和PyPy这样的东西。
Unladen Swallow主要是试图让Python运行得更快,但计划的一部分涉及将LLVM用于其后端。 LLVM可以(除其他外)生成本机机器代码输出。 Unladen Swallow的最后几个版本使用LLVM进行本机代码生成,但是 1)网站上的最新更新是从2009年底开始的,2)该版本的发行说明说: “Unladen Swallow团队不建议广泛采用2009Q3版本。”
Psyco作为Python的插件,基本上可以进行JIT编译,所以尽管它可以加快执行速度(在某些情况下会非常多),但它不会产生机器 - 代码可执行,您可以分发。简而言之,虽然它与您想要的类似,但它并不打算完全按照您的要求进行。
Shed Skin Python-to-C ++生成C ++作为输出,然后编译C ++并(可能)分发结果。 Shedskin目前处于0.5版本 - 也就是说,没有人声称它是一个已完成的,已发布的产品。另一方面,开发正在进行中,每个版本似乎都包含了相当大的改进。
PyPy是一个用Python编写的Python实现。他们的意图是允许“插入”代码生成而不影响实现的其余部分 - 但是当他们目前支持4种不同的代码生成模型时,我不相信它们中的任何一个会导致生成直接在硬件上运行的本机机器代码。
结论:工作已经完成并且正在完成你所做的事情的意图,但至少据我所知,没有任何我可以合理推荐的成品作为成品你现在真的可以依靠这份工作了。主要强调的是执行速度,而不是生成独立的可执行文件。
答案 4 :(得分:2)
你无法打开并阅读实际为python运行的代码。尝试
import dis
def foo():
for i in range(100):
print i
print dis.dis(foo)
这将显示foo
程序的(人类可读)字节码。等效地,您可以保存文件并从交互式python解释器中导入它。这将创建一个.pyc
文件,其基本名称与脚本相同。用十六进制编辑器打开它,你正在查看实际的python字节码。
区别的原因是python在版本之间更改了它的字节代码,因此您需要为每个版本的python分发不同版本的二进制版本。这将是一种痛苦。
使用C,它被编译为本机代码,因此字节代码更加稳定,使得仅二进制版本成为可能。
答案 5 :(得分:2)
是的,你可以 - 它被称为反汇编,并允许你完美地查看Safari的代码。问题是,C和其他语言一样,编译为本机代码,即CPU可以“理解”和执行的代码。
或多或少显然,CPU指令集中的抽象级别远远小于Python等高级语言的抽象级别。 CPU指令不关心“下载该URI”,而是更多“检查该位是否在硬件寄存器中设置”。
因此,总而言之,在查看机器代码时,本机应用程序中存在的复杂程度要高得多,因此很多人根本无法理解那里发生的事情,很难获得大的功能。图片。凭借经验和时间掌握,有可能 - 人们一直这样做,扭转应用程序和所有。
答案 6 :(得分:1)
因为C代码符合对象(机器)代码而python代码被编译成中间字节代码。我不确定你是否甚至指的是python的字节代码 - 你必须指的是直接可执行的源文件本身(隐藏你的字节代码!)。 C需要编译和链接。
答案 7 :(得分:0)
答案 8 :(得分:0)
Python脚本类似于查看用英语(或他理解的语言)编写的待办事项列表的人。每当必须完成这些事情时,这个人就必须做所有的工作。
如果男人不是每次都自己做步骤,而是创建并编程一个可以一次又一次地执行这些步骤的机器人(并且可能比他快),那个机器人就像C程序一样。 / p>
python案例中的人称为“解释器”,在C案例中称为“编译器”,C机器人称为编译程序/可执行文件。
当您查看python程序源时,您会看到待办事项列表。在机器人的情况下,您会看到齿轮,电机和电池等,它们与待办事项列表有很大不同。如果你能掌握C“待办事项”列表,它看起来有点像python代码,只是用不同的语言。
答案 9 :(得分:0)
并非所有C程序都需要反编译器。有许多以源代码形式分发的C代码。并且一些Python程序做需要反编译器,如果以字节码(.pyc文件)的形式分发。
但是,如果你的假设是有效的,那是因为C是compiled language而Python是interpreted language。
答案 10 :(得分:0)
G-WAN即时执行ANSI C脚本 - 就像Python脚本一样。
这可以是服务器端脚本(使用G-WAN作为Web服务器)或任何通用C程序,您可以链接任何现有的库。
哦,G-WAN C脚本比Python,PHP或Java快得多......