2009-11-07 75 views
42

Python有一個標誌-O,你可以執行解釋器。該選項將生成「優化」的字節碼(寫入.pyo文件),並給出兩次,它會放棄文檔。從Python的手冊頁:Python的基本優化模式的用途是什麼? (python -O)

-o打開基本的優化。這將編譯的(字節碼)文件從.pyc文件擴展名 更改爲.pyo。給定兩次, 會導致文檔被丟棄。

此選項的兩位,我看到它的主要特點是:

  • 地帶的所有斷言語句。這可以防止腐敗的程序狀態的速度。但是,你不需要大量的斷言來改變這種情況嗎?你有任何代碼,這是值得的(和理智?)

  • 去除所有文檔。在什麼應用中,內存使用如此重要,這是一場勝利?爲什麼不把所有東西都推入用C編寫的模塊?

這個選項有什麼用? 它有真實世界的價值嗎?

+5

你可以用它來翻轉測試套件中的閃爍燈光,讓它們偷偷地忽略斷言。歡呼!你已經完成了這個項目! (注意:不要這樣做) – Shayne 2014-12-02 08:55:51

回答

29

關於剝離斷言語句:這是C世界中的一個標準選項,許多人認爲ASSERT定義的一部分是它不能在生產代碼中運行。無論是其剝離出來,或者沒有有差別取決於少多少斷言有比多少工作那些聲稱要做:

def foo(x): 
    assert x in huge_global_computation_to_check_all_possible_x_values() 
    # ok, go ahead and use x... 

大多數斷言不是這樣的,當然,但要記住,你是非常重要的可以做這樣的事情。

至於剝離文檔字符串,它似乎是從一個簡單的時間古樸緩繳,但我想有內存受限的環境下它可以有所作爲。

+0

歷史很重要,好點。然而,我不想看玩具的例子,我想看看真實代碼中使用了什麼斷言,以及它是否有所作爲。 – u0b34a0f6ae 2009-11-07 14:16:41

+17

內存速度的增長速度遠遠低於CPU的速度,*特別是*如果您認爲我們繼續添加處理器比添加內存帶寬更快。所以,內存是新的磁盤,二級緩存是新的內存。 L2緩存很小*(與內存相比),而且它們實際上一直在變小。 (例如,Core2有6144KiB,i7只有256KiB。)因此,計數字節實際上又變得有用了。 – 2009-11-07 16:24:20

+2

OpenGL庫像PyOpenGL和pyglet在運行時會執行一些非常昂貴的安全檢查斷言,除非您指定-O。 – 2015-08-24 20:10:27

3

你幾乎已經想通了:它幾乎沒有做任何事情。除非你對RAM造成嚴重傷害,否則幾乎不會看到速度或內存的增加。

+0

或'if __debug__:r = long_running_function();斷言n - 0.01 DylanYoung 2017-12-14 21:50:22

5

我想-O最重的用戶是py2exepy2app和類似的。

我個人從未發現直接使用-O

+0

和*爲什麼* py2exe使用它? – u0b34a0f6ae 2009-11-07 14:15:51

+4

創建獨立可執行文件時,不需要文檔字符串。他們只佔用記憶中的空間。 – gnud 2009-11-07 18:21:15

7

如果您在頻繁調用的代碼中(例如在內部循環中)聲明,剝離它們肯定會有所作爲。極端示例:

$ python -c 'import timeit;print timeit.repeat("assert True")' 
[0.088717937469482422, 0.088625192642211914, 0.088654994964599609] 
$ python -O -c 'import timeit;print timeit.repeat("assert True")' 
[0.029736995697021484, 0.029587030410766602, 0.029623985290527344] 

在實際情況下,儲蓄通常會少得多。

剝離文檔可能會減少代碼的大小,從而縮小您的工作集。

在許多情況下,性能影響可以忽略不計,但是與優化一樣,唯一確定的方法就是測量。

+1

這個問題是關於真實世界的代碼。順便說一句,這是更實際:'python -mtimeit「」「assert(True)」'(在第一個參數設置) – u0b34a0f6ae 2009-11-07 14:15:16

+1

這似乎是一個奇怪的例子給我。您可以減少代碼中不重要的代碼,這種代碼對於我認爲的實際速度增益沒有太多的提示。一個現實的用例可能是一個操作,與執行操作相比,會產生大量的檢查費用昂貴的假設,但您相信它們應始終得到滿足。例如,如果我試圖返回拋物線的根,我可以檢查b ** 2 - 4 * a * c> 0以確保真正的根,如果這是我感興趣的。許多有用的公式有很多的約束。 – 2009-11-07 18:30:33

+2

另外,'assert'是一個聲明,我的意思是使用像「assert True'」,而不是'assert(True)'。這在添加消息時變得很重要,因爲「assert a == b」,必須爲真「」與assert(a == b,「必須爲true」)非常不同,特別是後者總是通過。 – 2009-11-07 18:31:10

6

我從來沒有遇到過使用-O的好理由。我一直認爲它的主要目的是爲了在未來某個時候增加一些有意義的優化。

+3

嗯,它確實做了一些事情,它們通常不是那麼有用。 – 2010-03-16 22:13:32

39

-O標誌的另一用途是內部變量__debug__的值設置爲False

所以,基本上,你的代碼可以有很多像「調試」路徑:

if __debug__: 
    # output all your favourite debugging information 
    # and then more 

其中,-O下運行時,甚至不會被包括在.pyo文件字節碼;一個窮人的C-ish #ifdef。

請記住,docstrings正在被丟棄只有當標誌爲-OO

+1

好吧,這讓我想到了另一個與-O相關的基本問題:通常,開發者的角色是決定使用/不使用優化模式會發生什麼,但用戶可以決定如何調用python解釋器,通常情況下!這使得你的例子接近無用,因爲你不能依賴正在使用的特定模式。 – u0b34a0f6ae 2009-11-08 23:21:43

+22

哇。我以爲你想知道真正的世界使用這個選項是什麼。感謝您在旁邊找到我的答案無用。順便說一句,如果你想讓某人證明Guido和其他Python核心團隊的選擇是正確的,那麼你不應該在這裏問問題;最後,你*可以*依賴於正在使用的特定模式,程序員可以控制是否使用優化;在SO中提出一個相關問題如何。我特此聲明你的假設是錯誤的,我的時間是在失敗之後。乾杯。對不起,令你失望。 – tzot 2009-11-09 01:05:40

+3

沒有理由讓我對我的問題獲得大量答案感到失望 - 我喜歡在stackoverflow中的對話。我的意思是我說的,但我談論你展示的例子。你自己展示它或你自己的事實根本沒有被判斷爲負面的。 – u0b34a0f6ae 2009-11-10 00:06:06

1

但是,你是否需要大量的斷言陳述來改變它?你有任何代碼,這是值得的(和理智?)

作爲一個例子,我有一段代碼,獲取圖形中的節點之間的路徑。我在函數的末尾斷言語句,以檢查路徑不包含重複:

assert not any(a == b for a, b in zip(path, path[1:])) 

我喜歡peace of mind and clarity,這個簡單的說法開發過程中給予。在生產中,代碼處理一些大圖,這一行可能佔用運行時間的66%。因此使用-O運行會顯着提高速度。