自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

不要使用Python開(kāi)發(fā)大型項(xiàng)目!

譯文 精選
開(kāi)發(fā) 開(kāi)發(fā)工具
本文將通過(guò)對(duì)變量聲明、模塊歸屬、依賴(lài)沖突、包管理、全局解釋器鎖以及并發(fā)和并行計(jì)算等方面的分析,向你解釋為什么不推薦在開(kāi)發(fā)大型項(xiàng)目時(shí)使用Python。

  譯者 | 朱先忠

  審校 | 千山

  本文將通過(guò)對(duì)變量聲明、模塊歸屬、依賴(lài)沖突、包管理、全局解釋器鎖以及并發(fā)和并行計(jì)算等方面的分析,向你解釋為什么不推薦在開(kāi)發(fā)大型項(xiàng)目時(shí)使用Python。

  Python并非你想象中那么棒!

  在開(kāi)發(fā)人員的職業(yè)生涯中,有一個(gè)特定的階段,即從為項(xiàng)目做出貢獻(xiàn)到發(fā)明自己的技術(shù)。對(duì)一些人來(lái)說(shuō)這個(gè)階段會(huì)來(lái)得更早一些,對(duì)另一些人來(lái)說(shuō)則可能更晚,而有些人根本就沒(méi)有這個(gè)階段。大多數(shù)職業(yè)生涯較長(zhǎng)的開(kāi)發(fā)人員都經(jīng)歷過(guò)這一點(diǎn),我稱(chēng)之為“自己動(dòng)手建造”階段。

  如果你是一位職業(yè)生涯較長(zhǎng)的開(kāi)發(fā)人員,那么你應(yīng)該知道本小節(jié)標(biāo)題的真正含義:它是如何工作的?用戶(hù)體驗(yàn)如何?應(yīng)用框架是什么?數(shù)據(jù)是如何流動(dòng)的?還有更多類(lèi)似的問(wèn)題。

  我不會(huì)在這里為你回答所有這些問(wèn)題。針對(duì)你要開(kāi)始的任何項(xiàng)目,它們都是一些非常具體的問(wèn)題。這些問(wèn)題中的每一個(gè)都值得至少使用一篇文章來(lái)加以解釋。

  不過(guò),我還是樂(lè)意回答一個(gè)問(wèn)題:哪種語(yǔ)言最適合項(xiàng)目開(kāi)發(fā)?

  你可能會(huì)認(rèn)為這也是因項(xiàng)目而異的非常具體的問(wèn)題。的確,你并沒(méi)有完全錯(cuò)。但每種編程語(yǔ)言都有一些缺陷。事實(shí)證明,Python也存在很多陷阱。尤其是當(dāng)你試圖用它來(lái)構(gòu)建一個(gè)大型程序時(shí)。

  變量不聲明導(dǎo)致的問(wèn)題

  Python禪宗(Zen of Python)的建議是:顯式優(yōu)于隱式。然而,在實(shí)際Python開(kāi)發(fā)中,隱式聲明比顯式聲明更常見(jiàn)。

  與此相反,大家不妨考慮下面這樣一小段C代碼:

  char notpython[50] = "This isn't Python.";

  在我們回到Python話(huà)題前,先讓我們深入了解一下上面這段C代碼。

  在此,char是一個(gè)類(lèi)型標(biāo)識(shí)符,它告訴你后面的所有內(nèi)容都與字符串有關(guān)?!皀otpython”是我給這個(gè)字符串起的名字。[50]告訴你,C將為此保留50個(gè)字符的內(nèi)存空間。不過(guò),在本例中,我可以得到19個(gè)字符——每個(gè)字符對(duì)應(yīng)一個(gè)空間位置,最后加上一個(gè)空字符\0。最后,用分號(hào)簡(jiǎn)潔地結(jié)束。

  這種顯式聲明在C語(yǔ)言中是必須的。如果省略顯式聲明,編譯器將出現(xiàn)相應(yīng)錯(cuò)誤提示!這種做事方式一開(kāi)始似乎既愚蠢又乏味,但卻是非常值得的。

  當(dāng)你在兩周或兩年后閱讀C代碼時(shí),例如你偶然發(fā)現(xiàn)了一個(gè)你不知道的變量,你只需檢查一下它的聲明。當(dāng)然,如果你給它起了一個(gè)有意義的名字,那么這會(huì)提供給你一個(gè)強(qiáng)有力的線(xiàn)索:有關(guān)它是什么,它在做什么,它需要在哪里,等等。

  現(xiàn)在,讓我們將其與Python進(jìn)行比較。

  在Python中,你幾乎可以一邊編寫(xiě)代碼一邊聲明新的變量。不過(guò),如果你沒(méi)有給它起一個(gè)有意義的名字或者至少留下一條注釋的話(huà),那么過(guò)些時(shí)候再閱讀此代碼時(shí)你會(huì)覺(jué)得問(wèn)題變得一團(tuán)糟。

  在Python中,除了深入分析有關(guān)源代碼之外,你根本無(wú)法理解變量在做什么。

  但是如果你在一個(gè)變量中有一個(gè)輸入錯(cuò)誤,那么就可能破壞你的整個(gè)代碼,因?yàn)椴淮嬖谙馛中那樣的保護(hù)聲明。

  如果你在做更小的項(xiàng)目,比如說(shuō)幾千行的代碼,那就沒(méi)關(guān)系;或者如果你的項(xiàng)目不是很復(fù)雜時(shí),也會(huì)存在什么問(wèn)題。但是當(dāng)有了更大的項(xiàng)目時(shí),就會(huì)遇到極大麻煩。

  是的,你可以在Python中進(jìn)行顯式變量聲明。但事實(shí)上,只有最勤奮的程序員才能做到這一點(diǎn)。更實(shí)際的情形是:當(dāng)編譯器沒(méi)有“抱怨”時(shí),許多人會(huì)完全忘記這些額外的代碼行。

  編寫(xiě)Python代碼是很快速的事情,而且對(duì)于小型和簡(jiǎn)單的項(xiàng)目來(lái)說(shuō),閱讀Python也很容易。

  然而,在閱讀和維護(hù)大型Python項(xiàng)目時(shí),例如當(dāng)尋找描述性變量名和注釋所有代碼方面,你最好是世界級(jí)程序員,否則你就完蛋了。

  模塊歸屬問(wèn)題

  如果你認(rèn)為事情不會(huì)變得更糟,那你就錯(cuò)了。

  變量在代碼中從何處開(kāi)始“存在”的問(wèn)題不僅僅源于隱式聲明。

  變量也可能來(lái)自其他模塊。它們的形式通常像my_module.my_variable()。如果你對(duì)這樣一個(gè)變量感到困惑,那么當(dāng)你檢查了它在主文件中的其他位置時(shí),你還沒(méi)有徹底解決問(wèn)題。

  你還需要檢查是否存在一行代碼,像下面其中之一:

  import my_module

  from another_module import my_module

  在第二行代碼中,你告訴編譯器你需要從一個(gè)包含更多內(nèi)容的模塊中得到哪個(gè)函數(shù)或變量。

  這是很煩人的事情,因?yàn)槟阍赑yPI(https://pypi.org/)上能找到更多的模塊,而且你還可以在計(jì)算機(jī)上導(dǎo)入任何其他Python文件。所以,快速搜索函數(shù)或變量并不總是有效。

  但有些情況下,問(wèn)題可能會(huì)變得更加糟糕。例如,有的模塊可能依賴(lài)于其他模塊。如果你運(yùn)氣不好,例如你導(dǎo)入了模塊A、B和C,但它們又依賴(lài)于模塊E、F、G和H,而模塊E、F、G和H又依賴(lài)于I、J和K。突然之間,你需要管理的模塊不是三個(gè),而變成了十個(gè)!

  更糟糕的是,有時(shí)這種依賴(lài)并不是一棵簡(jiǎn)單的依賴(lài)樹(shù)。假設(shè)B和C也依賴(lài)于M和N,J也依賴(lài)于M,C和H也依賴(lài)于Q……不必再?gòu)?qiáng)調(diào),你應(yīng)該明白了一切。

  這就像一個(gè)迷宮一樣。Python程序員把此稱(chēng)為“依賴(lài)地獄”——的確是真實(shí)存在的。

  而循環(huán)依賴(lài)算是迷宮中“最丑陋的野獸”。例如,如果模塊A依賴(lài)于模塊B,但模塊B也使用模塊A的一部分時(shí)——你的麻煩大了!

  對(duì)于小項(xiàng)目來(lái)說(shuō),這沒(méi)什么大不了的。但對(duì)于大的項(xiàng)目……你可能會(huì)一頭扎進(jìn)“原始叢林”。

  大規(guī)模的依賴(lài)沖突

  我還沒(méi)發(fā)泄完我對(duì)模塊的咆哮:不僅是模塊本身,還有它們的版本方面也存在問(wèn)題。

  原則上,Python擁有如此活躍的用戶(hù)群,并且許多模塊都定期更新,這是非常棒的。然而,只有一個(gè)問(wèn)題:并非所有版本的模塊都與其他模塊兼容。

  例如,假設(shè)你正在使用模塊A和B。這兩個(gè)模塊都依賴(lài)于模塊C。但是A在3.2或更高版本中需要C,而B(niǎo)在2.9或更低版本中需要C。你不在乎C,你只想要A和B。

  世界上沒(méi)有任何工具能幫你解決這場(chǎng)沖突。如果幸運(yùn)的話(huà),你會(huì)發(fā)現(xiàn)一個(gè)補(bǔ)丁,它是由與你遇到同樣問(wèn)題的人編寫(xiě)的。如果你沒(méi)那么幸運(yùn),你就得自己寫(xiě)補(bǔ)丁了。

  或者使用不同的軟件包?;蛘咄耆貙?xiě)其中一個(gè)包A或B,然后在需要錯(cuò)誤版本的C的任何地方找到解決方法。

  總之,在任何情況下,你都需要花費(fèi)額外的時(shí)間。

  這是一片“代碼叢林”,你需要耐心和一些工具來(lái)駕馭它才行。

  撇開(kāi)依賴(lài)沖突不談,還有一些不錯(cuò)的工具。例如,有一個(gè)名為pip的工具,可以使安裝軟件包變得容易。借助一個(gè)簡(jiǎn)單的文本文件“requirements.txt”,你可以指定要使用的軟件包和版本,而不是弄亂文件頭部。虛擬環(huán)境將所有軟件包放在一個(gè)地方,并與主要的Python安裝分開(kāi)。

  對(duì)于更大、更混亂的項(xiàng)目,還可以借助conda、YAML文件等途徑來(lái)解決上述問(wèn)題。

  但無(wú)論如何,你都需要學(xué)習(xí)如何使用每種工具。而且,你需要花最少的時(shí)間來(lái)處理這些問(wèn)題。

  不同機(jī)器上的Python問(wèn)題

  與上述“依賴(lài)地獄”世界聯(lián)系在一起的是另一個(gè)令人不安的話(huà)題。

  即使你已經(jīng)解決了機(jī)器上的所有依賴(lài)性問(wèn)題,并且Python像一匹新生的馬一樣平穩(wěn)運(yùn)行,也不能保證它會(huì)在其他人的機(jī)器上正常運(yùn)行。

  新生的馬會(huì)跑嗎?我不知道,但我似乎在努力讓自己在生物學(xué)方面比以往任何時(shí)候都更有學(xué)識(shí)。閑言少敘,讓我們回到Python話(huà)題。

  像pip、文本文件requirements.txt和虛擬環(huán)境這樣的工具將有助于你在一定程度上克服依賴(lài)地獄問(wèn)題。但是,這種便利僅限于本地情形。

  在每臺(tái)新機(jī)器上,你都需要檢查并可能重新安裝每個(gè)需求及其版本。

  唯一真正便攜的解決方案是借助Jupyter notebooks。在這里你可以用任何你喜歡的版本寫(xiě)東西。在Jupyter中,所有內(nèi)容都通過(guò)在線(xiàn)服務(wù)器運(yùn)行,因此你可以將這些文件發(fā)送給任何人,他們的確能夠“開(kāi)箱即用”。

  不過(guò),這種方法也存在一個(gè)明顯的缺點(diǎn):Jupyter notebooks只有圖形界面,而有時(shí)候僅僅使用圖形界面,很難處理包含許多相互關(guān)聯(lián)文件的大型項(xiàng)目。

  也許這就是為什么我從未在Jupyter notebooks上看到過(guò)大型項(xiàng)目,盡管它們確實(shí)存在。

  相比之下,其他一些計(jì)算機(jī)語(yǔ)言只使用虛擬機(jī),這類(lèi)問(wèn)題即可迎刃而解。

  除Pip之外的工具

  假設(shè)你已經(jīng)通過(guò)使用Jython或PyPy或類(lèi)似的解決方案將項(xiàng)目移植到不同的機(jī)器上。所有這些操作都比虛擬機(jī)稍顯笨拙。但是,至少它們能夠正常工作了!

  如果你正在組建一個(gè)大項(xiàng)目,你可能會(huì)集成C包、Fortran包等等。這樣做有很多好處:Python中可能不存在C包,而且通常速度更快。出于歷史原因,科學(xué)計(jì)算類(lèi)軟件包通常只存在于Fortran中。

  實(shí)際上,您將不得不使用諸如gcc、gfortran之類(lèi)的編譯器,或許還有其他更多的編譯器。

  這太麻煩了!在Python代碼中集成C模塊的文檔超過(guò)4500字——是本文的兩倍!Fortran相關(guān)的文檔也沒(méi)有那么短。

  用C語(yǔ)言構(gòu)建整個(gè)項(xiàng)目最初可能會(huì)耗費(fèi)更長(zhǎng)時(shí)間;但是,你可以防止出現(xiàn)必須處理多個(gè)編譯器和接口的情況。

  C是如此古老的語(yǔ)言,以致幾乎任何東西都有對(duì)應(yīng)的C語(yǔ)言包裝版本,甚至包括用戶(hù)友好的機(jī)器學(xué)習(xí)軟件包。

  使用全局解釋器鎖鎖定性能

  全局解釋器鎖(GIL)從Python誕生的第一天起就一直存在,它能夠使終端用戶(hù)的內(nèi)存管理變得非常簡(jiǎn)單。

  至少在較小的項(xiàng)目中,開(kāi)發(fā)人員在使用Python時(shí)根本不需要考慮計(jì)算機(jī)內(nèi)存問(wèn)題。我們不妨將其與C語(yǔ)言比較一下:在C語(yǔ)言中,需要為每個(gè)變量保留一些內(nèi)存。

  基本上,GIL能夠自動(dòng)計(jì)算一個(gè)變量在代碼的每個(gè)部分中被引用的次數(shù)。如果不再需要該變量,GIL就會(huì)釋放它所占用的內(nèi)存空間。

  在小型項(xiàng)目中,GIL有助于提高性能,因?yàn)椴槐匾膬?nèi)存空間會(huì)被及時(shí)清除掉。

  但在更大的項(xiàng)目中有一個(gè)問(wèn)題:GIL不喜歡多線(xiàn)程!

  當(dāng)多個(gè)指令線(xiàn)程在同一進(jìn)程資源上獨(dú)立運(yùn)行時(shí),這是一種高性能執(zhí)行程序的方法。機(jī)器學(xué)習(xí)模型很適合這樣訓(xùn)練。

  然而,只有一個(gè)小問(wèn)題:GIL一次只能在一個(gè)線(xiàn)程上工作。

  于是,會(huì)出現(xiàn)這樣的情況:例如變量A在線(xiàn)程1上執(zhí)行,而線(xiàn)程2已經(jīng)用完了變量A,那么它的內(nèi)存可能最終會(huì)被刪除。這種情況取決于GIL當(dāng)時(shí)在哪里運(yùn)行。

  因此,這可能會(huì)導(dǎo)致非常奇怪的錯(cuò)誤,正如你所想象的……

  這方面有一些變通辦法,但都不是很漂亮。另一種選擇方案是借助于多進(jìn)程來(lái)完成計(jì)算。但在沒(méi)有GIL的語(yǔ)言中,它通常不會(huì)像多線(xiàn)程那樣快。

  并發(fā)和并行計(jì)算依然讓人頭疼

  我們已經(jīng)看到了并發(fā)的一個(gè)缺點(diǎn)。在進(jìn)行多線(xiàn)程處理時(shí),全局解釋器鎖會(huì)降低速度,或者導(dǎo)致奇怪的錯(cuò)誤。

  同樣的缺點(diǎn)也存在于Python的協(xié)程中。

  線(xiàn)程和協(xié)程之間有一些細(xì)微的區(qū)別,但最重要的一點(diǎn)是:協(xié)程一次執(zhí)行一個(gè)任務(wù),而線(xiàn)程可以同時(shí)執(zhí)行多個(gè)任務(wù),二者都是并發(fā)實(shí)現(xiàn)的。

  當(dāng)你有需要大量等待的任務(wù)時(shí),協(xié)程非常有用,例如當(dāng)你正在閱讀網(wǎng)站數(shù)據(jù)并等待服務(wù)器響應(yīng)時(shí)的情形。協(xié)程不會(huì)讓計(jì)算機(jī)無(wú)所事事,而是給它分配另一項(xiàng)任務(wù)。

  另一方面,當(dāng)你有幾個(gè)任務(wù)很耗時(shí)但不需要太多CPU消耗,也不需要太多等待時(shí),線(xiàn)程是很有用的。流式數(shù)據(jù)就是一個(gè)例子。

  如果你有一個(gè)CPU密集型任務(wù),并且你想充分利用你的硬件,你可能想嘗試一下使用并行計(jì)算。

  多進(jìn)程會(huì)成為你最好的朋友——它基本上是告訴計(jì)算機(jī)使用多個(gè)內(nèi)核進(jìn)行計(jì)算,從而節(jié)省大量時(shí)間。

  不過(guò),線(xiàn)程、協(xié)同程序和多進(jìn)程這三種技術(shù)都面臨類(lèi)似的問(wèn)題。它們?cè)赑ython中實(shí)現(xiàn)起來(lái)并不難。但是代碼看起來(lái)很笨重,很難閱讀,尤其是對(duì)于初學(xué)者來(lái)說(shuō)。

  相比來(lái)說(shuō),Clojure、Go和Haskell等語(yǔ)言在并發(fā)性和并行性方面性能要好得多。但是,如果你不是在處理緩慢或密集的進(jìn)程,那么你根本不必考慮這樣的方案。但如果當(dāng)你遇到這樣的問(wèn)題時(shí),那么你可能需要考慮選擇語(yǔ)言的問(wèn)題了。

  用哪一種語(yǔ)言代替Python?

  Python并不全是邪惡的,但它的確也存在缺點(diǎn)。

  因此,如果你想要明確說(shuō)明的變量和開(kāi)發(fā)良好的包,而這些包不會(huì)讓你輕易陷入依賴(lài)地獄,那么你可以選擇C語(yǔ)言。此外,如果你想要任何機(jī)器都可以移植的東西,那么Java、Clojure或Scala都是不錯(cuò)的選擇。因?yàn)樗鼈冊(cè)谔摂M機(jī)上運(yùn)行,所以你不會(huì)遇到與Python相同的問(wèn)題。

  還有,如果你想執(zhí)行大而慢的任務(wù),你可能想試試Go或Haskell。盡管一開(kāi)始,它們比Python更難學(xué)習(xí),但你投入的時(shí)間是有回報(bào)的。特別是,你總可以把多種語(yǔ)言組合起來(lái)使用。

  Python非常適合快速編寫(xiě)腳本、初稿,甚至適合中等規(guī)模的項(xiàng)目。我認(rèn)識(shí)的許多開(kāi)發(fā)人員都用Python編寫(xiě)初稿和測(cè)試運(yùn)行,然后再使用C、Go或Clojure重寫(xiě)重要的部分。這使代碼執(zhí)行更快,而且你仍然可以享受Python提供的優(yōu)勢(shì)。

  在大型項(xiàng)目中,Python并不是被禁止使用,只不過(guò)這可能不是唯一使用的語(yǔ)言而已。你可以通過(guò)Python像膠水一樣將C、Go或Clojure中的代碼拼接在一起。此外,如果你已經(jīng)達(dá)到了自己構(gòu)建的階段,那么請(qǐng)記住:沒(méi)有任何一種語(yǔ)言是絕對(duì)優(yōu)秀的!

  總之,盡管Python有缺點(diǎn),但它的確很酷,而且也很方便。通過(guò)使用Python集成其他語(yǔ)言中的代碼,你總是可以繞過(guò)有關(guān)難點(diǎn)并最終解決問(wèn)題。

  譯者介紹

  朱先忠,51CTO社區(qū)編輯,51CTO專(zhuān)家博客、講師,濰坊一所高校計(jì)算機(jī)教師,自由編程界老兵一枚。早期專(zhuān)注各種微軟技術(shù)(編著成ASP.NET AJX、Cocos 2d-X相關(guān)三本技術(shù)圖書(shū)),近十多年投身于開(kāi)源世界(熟悉流行全棧Web開(kāi)發(fā)技術(shù)),了解基于OneNet/AliOS+Arduino/ESP32/樹(shù)莓派等物聯(lián)網(wǎng)開(kāi)發(fā)技術(shù)Scala+Hadoop+Spark+Flink等大數(shù)據(jù)開(kāi)發(fā)技術(shù)。

  原文標(biāo)題:Don’t use Python… if you’re starting a big project,作者:Ari Joury

  鏈接:https://thenextweb.com/news/dont-use-python-for-big-projects

責(zé)任編輯:張潔 來(lái)源: 51CTO技術(shù)棧
相關(guān)推薦

2015-08-26 10:36:32

ios開(kāi)發(fā)漫談

2015-08-31 10:11:43

iOS大項(xiàng)目開(kāi)發(fā)

2021-05-12 08:54:56

FastAP web 框架數(shù)據(jù)庫(kù)操作

2012-04-01 15:03:39

大型項(xiàng)目開(kāi)發(fā)者

2019-12-16 11:16:22

Git子模塊項(xiàng)目

2024-12-26 08:00:38

2012-03-16 14:23:00

框架

2018-01-08 08:28:44

Linux命令

2012-03-16 14:23:00

框架

2023-10-06 12:04:41

ORM關(guān)系型數(shù)據(jù)庫(kù)

2021-01-13 09:34:45

項(xiàng)目Gson框架

2024-01-22 09:17:35

2020-04-30 09:24:46

Go項(xiàng)目語(yǔ)言

2021-01-26 05:39:06

項(xiàng)目模塊代碼

2024-02-20 22:13:49

SQL語(yǔ)句編程

2012-09-23 09:38:13

鐵路客票系統(tǒng)

2019-10-10 10:30:26

MVCModelController

2020-09-15 06:13:05

Vue.jsJavaScript框架

2015-06-11 09:59:36

數(shù)據(jù)中心UPS

2022-12-06 08:26:16

SpringAOPthis調(diào)用方法
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號(hào)