2010-10-06 93 views
3

如果我編寫一個python腳本,任何人都可以簡單地將一個編輯器指向它並閱讀它。但對於使用C語言編寫的程序,必須使用反編譯器和十六進制表等。這是爲什麼?我的意思是我根本無法打開Safari瀏覽器並查看其代碼。爲什麼C程序需要反編譯器,但python程序不需要?

+0

應該有年齡段的標籤。 – Yehonatan 2010-10-06 04:47:09

+0

@Yehonatan:我認爲收集所有關於編程的新手問題的標籤是一個好主意 – pyfunc 2010-10-06 05:03:49

+0

@pyfunc:[管理層不同意。](http://blog.stackoverflow.com/2010/08/the-death-of-meta -tags /) – intuited 2010-10-06 05:18:29

回答

13

注意:作者拒絕在這個主題的深厚專業知識。有些斷言可能不正確。

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之類的依賴項。

10

Python是一種腳本語言,通過中間人在虛擬機中運行。 C是一種編譯語言,將代碼編譯爲二進制代碼,計算機可以在沒有所需的額外東西的情況下運行該代碼。

+0

是否有可能編譯python到一個可執行的二進制文件,然後簡單地分發? – Ali 2010-10-06 04:33:23

+2

@Ali:不,沒有合理的方式去做,不要相信別的。 – 2010-10-06 04:45:31

1

因爲C代碼符合對象(機器)代碼,並且python代碼被編譯爲中間字節代碼。我不確定你是否指的是python的字節碼 - 你必須引用可直接執行的源文件本身(隱藏你的字節碼!)。 C需要編譯和鏈接。

0
  • Python腳本只有在運行時才被解析並轉換爲二進制文件 - 即它們是文本文件,您可以使用編輯器讀取它們。
  • C代碼被編譯並鏈接到一個可執行的二進制文件,然後才能運行。通常,只有這個可執行的二進制文件是分佈式的 - 因此你需要一個反編譯器。你可以隨時查看源代碼,如果你有權訪問它。
+0

我認爲OP意味着無法讀取Safari可執行文件本身。 – intuited 2010-10-06 04:15:01

+0

@intuited嗯..有道理 - 刪除它。 – Amarghosh 2010-10-06 04:17:17

+0

然後是否可以將python編譯爲可執行的二進制文件,然後簡單地分發該文件? – Ali 2010-10-06 04:32:35

2

您無法打開並閱讀實際爲python運行的代碼。嘗試

import dis 

def foo(): 
    for i in range(100): 
     print i 

print dis.dis(foo) 

這會顯示foo程序的(人類可讀的)bytcode。等價地,您可以保存該文件並從交互式Python解釋器中導入它。這將創建一個.pyc文件,其腳本具有相同的基本名稱。用十六進制編輯器打開它,然後查看實際的python字節碼。

不同之處在於,python在不同版本之間更改了字節碼,因此您需要爲每個版本的Python分發不同版本的二進制版本。這將是一個痛苦。

隨着C,它被編譯爲本地代碼,所以字節代碼更加穩定,使得只有二進制版本成爲可能。

5

這是一個很大的話題。你應該看看你當地友好的計算機科學課程,你會發現很多有關這個主題的偉大的東西。

簡短的答案是Python是一種「解釋」語言,這意味着它需要一個機器語言程序(python解釋器)來運行python程序,並添加一個間接層。 C或C++是不同的。它們直接編譯爲機器碼,可直接在處理器上運行。

然而,這裏有很多額外的伏都教。從技術上講,Python被編譯爲一個字節碼,而現代解釋器的編譯越來越多,所以編譯和解釋代碼之間的界限越來越模糊。

2

是的,你可以 - 它被稱爲反彙編,並允許你很好地看看Safari的代碼。問題是,C和其他語言一樣,編譯爲本地代碼,即CPU可以「理解」並執行的代碼。

或多或少顯然,CPU指令集中的抽象級別遠遠低於像Python這樣的高級語言。CPU指令不關心「下載該URI」,而是更多地「檢查該位是否設置在硬件寄存器中」。

因此,總之,在本機應用程序中出現的複雜程度在查看機器代碼時要高得多,因此很多人根本無法理解那裏發生的事情,很難獲得大的圖片。隨着經驗和時間的掌握,人們可能會一直這樣做,扭轉應用和所有情況。

+0

然後可以編譯python到一個可執行的二進制文件,然後簡單地分發它? – Ali 2010-10-06 04:32:59

0

Python腳本與查看用英語(或他理解的語言)編寫的待辦事項列表的人類似。這個人必須完成所有的工作,每次都要完成這些事情。如果這個人不是每次都獨自完成這些步驟,而是創建並編程一個能夠一次又一次地執行這些步驟的機器人(並且可能比他更快),那麼這個機器人就類似於C程序。

python情況下的人稱爲「解釋器」,在C情況下稱爲「編譯器」,C機器人稱爲編譯程序/可執行文件。

當您查看python程序源代碼時,您會看到待辦事項列表。在機器人的情況下,你會看到齒輪,電機和電池等,這些與待辦事項列表看起來有很大不同。如果你能夠掌握C的「待辦事項」列表,它看起來有點像Python代碼,只是用不同的語言。

+1

編譯Python腳本。它們只是爲僅存在於軟件中的機器編譯的。 Python的「解釋器」是該機器的一個模擬器,它具有一個嵌入式編譯器,並將其移植到頂層,以便將該腳本編譯爲該虛擬機器的目標代碼格式。 – 2010-10-06 04:44:18

+0

非常感謝 - 我知道那些細節。假設問題提出者的代謝率適中,我可以很容易地進行消化。 – Rajan 2010-10-06 05:23:58

0

並非所有的C程序都需要反編譯器。有很多C代碼以源代碼形式分發。如果分發爲字節碼(.pyc文件),一些Python程序需要反編譯器。

但是,就您的假設有效而言,這是因爲C是compiled language而Python是interpreted language

+0

python不僅僅是java的解釋性語言。它在虛擬機上運行。 – aaronasterling 2010-10-06 04:28:35

3

在你問到的幾個註釋中:「是否可以將python編譯爲可執行的二進制文件,然後簡單地分發它?

從理論的角度來看,毫無疑問答案是肯定的 - 一個Python程序可以被編譯成完全編譯的機器代碼,並且可以作爲完全編譯的機器代碼分發。

從實踐的角度來看,它有更多的問題。有一些東西,如Unladen Swallow,Psyco,Shed Skin和PyPy,你可能想知道。

  1. Unladen Swallow主要是在製作的Python運行更快的嘗試,但部分計劃這樣做,包括使用LLVM其後端。 LLVM可以(除其他外)生成本機機器碼輸出。 Unladen Swallow的最後幾個版本使用LLVM進行本地代碼生成,但是 1)網站上的最新更新是從2009年底開始的,2)該版本的發行說明說:「Unladen Swallow團隊並不建議廣泛採用2009Q3版本。「

  2. Psyco作爲一個基本上可以進行JIT編譯的Python插件,所以即使它可以加快執行速度(在某些情況下相當多),但它不會生成可分發的機器代碼可執行文件。總之,雖然它與你想要的類似,但並不打算按照你的要求去做。

  3. Shed Skin Python-to-C++生成C++作爲其輸出,然後編譯C++並(可能)分發結果。 Shedskin目前在0.5版本 - 即沒有人聲稱它是一個完成的,發佈的產品。另一方面,開發正在進行中,每個版本似乎都包含相當大的改進。

  4. PyPy是用Python編寫的Python實現。他們的意圖是允許代碼生成「插入」而不影響其餘的實現 - 但他們目前支持4種不同的代碼生成模型,我不相信它們中的任何一個會生成本地機器代碼直接在硬件上運行。

底線:工作已經完成,目前正在與做你問什麼的意圖完成,但至少據我所知,這不是真的什麼我可以合理建議作爲成品,你現在真的可以依靠做這項工作了。主要重點在於執行速度,而不是生成獨立的可執行文件。

0

G-WAN在運行時執行ANSI C腳本 - 就像Python腳本一樣。

這可以是服務器端腳本(使用G-WAN作爲Web服務器)或任何通用C程序,您可以鏈接任何現有的庫。

哦,和G-WAN C腳本比Python,PHP或Java快得多......

+0

這與此有關嗎? – NullUserException 2010-10-06 15:28:09

相關問題