摘要:之痛原文地址譯者校正實用編程指南這是我在所做的演講。事實一和二共同造成了計算機(jī)設(shè)備結(jié)構(gòu)與世界人類需求的一個沖突。就是為了解決之前的老的字符集問題。值意味著,失敗時將會返回一個標(biāo)準(zhǔn)的替代字符。將使用進(jìn)行了解碼。
Unicode之痛
原文地址: http://nedbatchelder.com/text...
譯者: yudun1989 校正: sicklife
實用Unicode編程指南
這是我在 Pycon2012 所做的演講。你可以閱讀本頁的幻燈片和文字,或者直接在瀏覽器中打開 演示 ,或者來看現(xiàn)場視頻。
同時,點擊文章的圖片將會進(jìn)入所在幻燈片的的對應(yīng)位置,圖片中使用了 Symbola 字體,但是如果想要顯示一些特殊符號的話,則需先將該字體下載下來。
大家好,我是Ned Batchelder.我已經(jīng)有十年的Python編程經(jīng)驗,這意味著,很多很多的時候,我與其他程序員一樣,犯過很多 Unicode 的編碼錯誤。
如果你和其他 Python 程序員一樣,那你肯定也碰到過如下情況:你編寫了一段很漂亮的代碼,事情看起來很順。然后某一天一個很奇怪的“方言字符”不知道從哪冒了出來,你的程序中就開始大量涌現(xiàn) UnicodeErrors 。
你好像知道這種問題應(yīng)該怎樣解決,于是呢,就去在錯誤出現(xiàn)的地方添加了 encode 和 decode ,但是 UnicodeError 又開始出現(xiàn)在其他的地方。于是你又在另外一個地方添加了 decode 抑或 encode 。在你玩過一段“編碼打地鼠”游戲之后,問題似乎被解決。
之后某一天,另一種“方言字符”又在另外一個地方出現(xiàn)了。然后你不得不又去玩這種“打地鼠”直到問題解決掉。
現(xiàn)在你的程序終于可以運行。但是你既煩惱又不適,這個問題花費了太多時間,你知道這樣解決“正確”,于是開始憎恨自己。你對 Unicode 的主要了解就是你很討厭它。
你不想去了解怪異的字符集,你只想要寫一個你認(rèn)為不是很糟糕的程序。
你不必去玩打地鼠游戲. Unicode 會有些麻煩,但是它并不難。了解了相關(guān)知識并且加以練習(xí),你也可以方便的優(yōu)雅的解決相關(guān)問題。
接下來我會教給你 five Facts of lie,然后給你一些專業(yè)建議來解決 Unicode 問題。下面的內(nèi)容將會包含 Unicode 基本知識,如何在 Python 2 和 Python 3 中來實現(xiàn)。他們有一定差異,但是你使用的基本策略都是一樣的。
世界 & Unicode
我們從 Unicode 基本知識開始。
事實之一:計算機(jī)中的一切均為 bytes(字節(jié))。硬盤中的文件為一系列的 byte 組成,網(wǎng)絡(luò)中傳輸?shù)闹挥?byte。所有的信息,在你寫的程序中進(jìn)進(jìn)出出的,均由 byte 組成。
孤立的 byte 是毫無意義的,所以我們來賦予它們含義。
為了表示各種文字,我們有大約 50 年的時間都在用 ASCII 碼。每一個 byte 被賦予 95 種符號的一種,所以,當(dāng)我給你發(fā)送 byte 值為 65 的時候,你知道我想表達(dá)一個大寫的 A。
ISO Latin 1,或者 8859-1 對 ASCII 的 96 種字符進(jìn)行了擴(kuò)展。這也許是你用一個 byte 可以做的最多的事情了。因為 byte 中沒有容量可以存儲更多的符號了。
在 Windows 中增加了另外 27 種字符,這種叫做 CP1252 編碼。
事實之二是,世界上的字符遠(yuǎn)遠(yuǎn)比256個要多。一個簡單的byte不能夠表達(dá)世界范圍內(nèi)的字符。在你玩”編碼打地鼠”的時候,你多么的希望世界上所有的人都說英語,但是事實并不是這樣,人們需要更多的符號來交流。
事實一和二共同造成了計算機(jī)設(shè)備結(jié)構(gòu)與世界人類需求的一個沖突。
當(dāng)時為了解決沖突嘗試了多種途徑。通過一個 byte 來與符號或者字符進(jìn)行對應(yīng)的編碼,每一種解決途徑都沒有解決事實二中的實質(zhì)問題。
當(dāng)時有很多一個 byte 的編碼,都沒有能夠解決問題。每一個都只能解決人類語言的一部分。但是他們不能解決所有的文字問題。
人們開始創(chuàng)造兩個 byte 的字符集,但是仍然像碎片一樣,只能夠服務(wù)于不同地域的一部分人。
當(dāng)時產(chǎn)生了不同的標(biāo)準(zhǔn),諷刺的是,他們都不足以滿足所有的符號的需求。
Unicode 就是為了解決之前的老的字符集問題。Unicode 分配整形,被成為代碼點( UNICODE 的字符被成為代碼點( CODE POINTS )用 U 后面加上 XXXX 來表現(xiàn),其中, X 為16進(jìn)制的字符)來表示字符。它有 110 萬的代碼點,其中有十一萬被占用,所以它可以有很多很多的空間可供未來的增長使用。
Unicode 的目的是包含一切,它從 ASCII 開始,包含了數(shù)以千計的代碼,包含這著名的—-雪人??,包含了世界上所有的書寫系統(tǒng),而且一直在被擴(kuò)充。比如,最新的更新中,就有一大堆沒用的詞匯。
這里有六個的異國 Unicode 字符。 Unicode 代碼點寫成 4- , 5- ,或者 6 位的十六進(jìn)制編碼,同時有一個 U 的前綴。每一個字符都有一個用 ASCII 字符規(guī)定的名稱。
所以說 Unicode 提供了所有我們需要的字符的空間。但是我們?nèi)匀恍枰幚硎聦嵰恢兴龅降膯栴}:計算機(jī)只能看懂 bytes 。我們需要一種用 bytes 來表示 Unicode 的方法這樣才可以存儲和傳播他們。
Unicode 標(biāo)準(zhǔn)定義了多種方法來用 bytes 來表示成代碼點,被成為 encoding 。
UTF-8 是最流行的一種對 Unicode 進(jìn)行傳播和存儲的編碼方式。它用不同的 bytes 來表示每一個代碼點。ASCII 字符每個只需要用一個 byte ,與 ASCII 的編碼是一樣的。所以說 ASCII 是 UTF-8 的一個子集。
這里我們展現(xiàn)了幾個怪異字符的 UTF8 的表示方法。 ASCII 字符 H 和 I 只用一個 byte 就可以表示。其他的根據(jù)代碼點的不同使用了兩個或者三個 bytes 。盡管有些并不常用,但是一些代碼點使用到四個 bytes。
Python 2
好,說完了這么多理論知識,我們來講一講 Python 2
在 Python2 中,有兩種字符串?dāng)?shù)據(jù)類型。一種純舊式的文字: “str” 對象,存儲 bytes 。如果你使用一個 “u” 前綴,那么你會有一個 “unicode” 對象,存儲的是 code points 。在一個 unicode 字符串中,你可以使用反斜杠 u(u) 來插入任何的 unicode 代碼點。
你可以注意到 “string” 這個詞是有問題的。不管是 “str” 還是 “unicode” 都是一種 “string” ,這會吸引叫它們都是 string ,但是為了直接還是將它們明確區(qū)分來。
如果想要在 unicode 和 bytes 間轉(zhuǎn)換的話,兩者都有一個方法。 Unicode 字符串會有一個 .encode 方法來產(chǎn)生 bytes , bytes 串會有一個 .decode 方法來產(chǎn)生 unicode 。每個方法中都有一個參數(shù)來表明你要操作的編碼類型。
我們可以定義一個 Unicode 字符串叫做 my_unicode ,然后看這九個字符,我們使用 encode 方法來創(chuàng)建 my_unicode 的 bytes 串。會有 19 個 bytes ,想你所期待的那樣。將 bytes 串來 decode 將會得到 utf-8 串。
不幸的是,如果指明的編碼名稱錯誤的話,那么 encode 和 decode 會產(chǎn)生錯誤。現(xiàn)在嘗試 encode 我們的幾個詭異的字符到 ascii ,會失敗。因為 ascii 只能表示 0-127個 字符中的一個。然而我們的 Unicode 字符串早已經(jīng)超出了范圍。
拋出的異常為 UnicodeEncodeError ,它展現(xiàn)了你使用的編碼方式, “codec” 即(coder/decoder),展現(xiàn)了導(dǎo)致問題的字符的位置。
解碼同樣會知道出一些問題。現(xiàn)在我們?nèi)グ岩粋€ UTF-8 字符串解碼成 ASCII ,會得到一個 UnicodeDecodeError ,原因一樣, ASCII 只接受 127 內(nèi)的值,我們的 UTF-8字 符串超出了范圍。
盡管 UTF-8 不能解碼成任何的 bytes 串,我們嘗試來 decode 一些垃圾信息。同樣也產(chǎn)生了 UnicodeDecodeError 錯誤。最終, UTF-8 的優(yōu)勢是,有效的 bytes 串,將會幫助我們來創(chuàng)建高魯棒性的系統(tǒng):如果數(shù)據(jù)無效的話,數(shù)據(jù)不會被接受。
當(dāng)編碼或者解碼的時候,你可以指明如果 codec 不能夠處理數(shù)據(jù)的時候,會發(fā)生什么情況。 encode 或者 decode 時候的第二個參數(shù)指明了規(guī)則。默認(rèn)的值是 “strict” ,意味著像剛才一樣,會拋出一個異常。
“replace” 值意味著,失敗時將會返回一個標(biāo)準(zhǔn)的替代字符。當(dāng)編碼的時候,替代值是一個問號,所以任何不能被編碼的值將會產(chǎn)生一個 ”?”。
一些其他的 handler 非常有用。”xmlcharrefreplace” 將會產(chǎn)生一個完全替代的 HTML/XML 字符,所以 u01B4 將會變成 “?” (因為十六進(jìn)制的 01B4 是十進(jìn)制的 436 )。如果你需要將返回的值來輸出到 html 文件中的話,將會非常有用。
注意要根據(jù)不同的錯誤原因使用不同的錯誤處理方式。”replace” 是一個處理不能被解析的數(shù)據(jù)的自衛(wèi)型方式,會丟失數(shù)據(jù)。”xmlcharrefreplace” 會保護(hù)所有的原始數(shù)據(jù),在 XML 轉(zhuǎn)義符可以使用的時候來輸出數(shù)據(jù)。
你也可以指定在解碼時的錯誤處理方式。”ignore” 會直接將不能解碼的 bytes 丟掉。”replace” 將會直接添加 Unicode U+FFFD ,給有問題的 bytes 來直接替換成”替換字符”。注意因為解碼器不能解碼這些數(shù)據(jù)。它并不知道到底有多少 Unicode 字符。解碼我們的 UTF-8 字符串成為 ASCII 制造出了 16 個”替換字符”。每個 byte 不能被解析都被替換掉了。然而這些 bytes 只想要表示 6 個 Unicode 字符。
Python 2 已經(jīng)試圖在處理 unicode 和 byte 串的時候變得有用些。如果你系那個要把 Unicode 字符串串和 byte 字符串來組合起來的話, Python 2 將會自動的將 byte 串來解碼成 unicode 字符串。從而產(chǎn)生一個新的 Unicode 字符串。
比如,我們想要連接 Unicode 串 “hello” 和一個 byte 字符串 “world”。結(jié)果是一個 Unicode 的 “hello world”。在我們看來。Python 2 將 “world” 使用 ASCII codec 進(jìn)行了解碼。這次在解碼中使用的字符集的值與 sys.getdefaultencoding() 的值相等。
這里這個系統(tǒng)中的字符集為 ASCII, 因為這是唯一合理的一種猜測: ASCII 被如此廣泛接受,它是這么多編碼的子集,不太會是錯誤的。
當(dāng)然,這些隱藏的編碼轉(zhuǎn)換不能免疫于解碼錯誤。如果你想要連接 一個 byte 字符串和一個 unicode 字符串,并且 byte 字符串不能被解碼成 ASCII 的話,將會拋出一個 UnicodeDecodeError。
這就是那些可惡的 UnicodeError 的圓圈。你的代碼中包含了 unicode 和 byte 字符串,只要數(shù)據(jù)全部是 ASCII 的話,所有的轉(zhuǎn)換都是正確的,一旦一個非 ASCII 字符偷偷進(jìn)入你的程序,那么默認(rèn)的解碼將會失敗,從而造成 UnicodeDecodeError 的錯誤。
Python 2 的哲學(xué)就是 Unicode 字符串和 byte 字符串是可以混合的,它試圖去通過自動轉(zhuǎn)換來減輕你的負(fù)擔(dān)。就像在 int 和 float 之間的轉(zhuǎn)換一樣, int 到 float 的轉(zhuǎn)換不會失敗,byte 字符串到 unicode 字符串會失敗。
Python 2 悄悄掩蓋了 byte 到 unicode 的轉(zhuǎn)換,讓程序在處理 ASCII 的時候更加簡單。你付出的代價就是在處理非 ASCII 的時候?qū) ?/p>
有很多方法來合并兩種字符串(一個 byte 字符串和一個 unicode 字符串),所有的方法都會先將 byte 轉(zhuǎn)換為 unicode,所以處理它們的時候你必須多加小心。
首先我們使用 ASCII 格式字符串,和 unicode 來結(jié)合。那么最終的輸出將會變成 unicode。返回一個 unicode 字符串。
之后我們將兩個交換一下:一個 unicode 格式的字符串和一個 byte 串再一次合并,生成了一個 unicode 字符串,因為 byte 串可以被解碼成 ASCII。
簡單的去打印出一個 unicode 字符串將會調(diào)用隱式的編碼:輸出總會是 bytes, 所以在 unicode 被打印之前必須被編碼成 byte 串。
接下來的事情非常不可理解:我們讓一個 byte 串編碼成 UTF-8,卻得到一個錯誤說不能被解碼成 ASCII!這里的問題是 byte 串不能被編碼,要記住編碼是你將 Unicode 變成了 byte 串。所以想要執(zhí)行你的操作的話,Python2 需要的是一個 unicode 字符串,隱式的將你的字符串解碼成 ASCII。
最后,我們將 ASCII 字符串編碼成 UTF-8。現(xiàn)在我們進(jìn)行相同的隱式編碼操作,因為字符串為 ASCII,編碼成功。并且將它編碼成了 UTF-8 ,打印出了原始的 byte 字符串,因為 ASCII 是 UTF-8 的一個子集。
最重要的事實之三:byte 和 unicode 都非常重要,你必須將兩個都處理好。你不能假設(shè)所有的字符串都是 byte,或者所有的字符串都是 unicode,你必須適當(dāng)?shù)剡\用它們,必要時轉(zhuǎn)換它們。
Python 3
我們看到了 Python 2 版本中有關(guān) Unicode 之痛。現(xiàn)在我們看一下 Python 3,在 Python 2 到 Python 3 中最重要的變化就是它們對 Unicode 的處理。
跟 Python 2 類似,Python 3 也有兩種類型,一個是 Unicode,一個是 byte 碼。但是它們有不同的命名。
現(xiàn)在你從普通文本轉(zhuǎn)換成 “str” 類型后存儲的是一個 unicode, “bytes” 類型存儲的是 byte 串。你也可以通過一個 b 前綴來制造 byte 串。
所以在 Python 2 中的 “str” 現(xiàn)在叫做 “bytes”,而 Python 2 中的 “unicode” 現(xiàn)在叫做 “str”。這比起Python 2中更容易理解,因為 Unicode 是你總想要存儲的內(nèi)容。而 bytes 字符串只有你在想要處理 byte 的時候得到。
Python 3 中對 Unicode 支持的最大變化就是沒有對 byte 字符串的自動解碼。如果你想要用一個 byte 字符串和一個 unicode 相連接的話,你會得到一個錯誤,不管包含的內(nèi)容是什么。
所有這些在 Python 2 中都有隱式的處理,而在 Python 3 中你將會得到一個錯誤。
另外如果一個 Unicode 字符串和 byte 字符串中包含的是相同的 ASCII 碼,Python 2 中將認(rèn)為兩個是相等的,而在 Python 3 中不會。這樣做的結(jié)果是 Unicode 中的鍵不能找到 byte 字符串中的值,反之亦然,然而在 Python 2 中是可行的。
這樣徹底了改變了 Python 3 中的 Unicode 痛楚之源。在 Python 2 中,只要你使用 ASCII 數(shù)據(jù),那么混合 Unicode 和 byte 將會成功,而在 Python 3 會直接忽略數(shù)據(jù)而失敗。
這樣的話,在 Python 2 中所遇到的,你認(rèn)為你的程序是正確的但是最后發(fā)現(xiàn)由于一些特殊字符而失敗的錯誤就會避免。
Python 3 中,你的程序馬上就會產(chǎn)生錯誤,所以即使你處理的是 ASCII 碼,那你也必須處理 bytes 和 Unicode 之間的關(guān)系。
Python 3 中對于 bytes 和 unicode 的處理非常嚴(yán)格,你被迫去處理這些事情。這曾經(jīng)引起爭議。
這樣處理的原因之一是對讀取文件的變化,Python 對于讀取文件有兩種方式,一種是二進(jìn)制,一種是文本。在 Python 2 中,它只會影響到行尾符號,甚至在 Unix 系統(tǒng)上的時候,基本沒有區(qū)別。
在 Python 3中。這兩種模式將會返回不同的結(jié)果。當(dāng)你用文本模式打開一個文件時不管你是用的 “r” 模式或者默認(rèn)的模式,讀取成功的文件將會自動轉(zhuǎn)碼成 unicode ,你會得到 str 對象。
如果你用二進(jìn)制模式打開一個文件,在參數(shù)中輸入 “rb” ,那么從文件中讀取的數(shù)據(jù)會是 bytes,對它們沒有任何處理。
隱式的對 bytes 到 unicode 的處理使用的是 locale.getpreferedencoding() ,然而它有可能輸出你不想要的結(jié)果。比如,當(dāng)你讀取 hi_utf8.txt 時,他被解碼成語言偏好中所設(shè)置的編碼方式,如果我們這些例子在 Windows 中創(chuàng)建的話,那么就是 “cp1252” 。像 ISO 8859-1, CP-1252 這些可以得到任意的 byte 值,所以不會拋出 UnicodeDecodeError ,當(dāng)然也意味著它們會直接將數(shù)據(jù)解碼成 CP-1252,制造出我們并不需要的垃圾信息。
為了文件讀取正確的話,你應(yīng)該指明想要的編碼。open 函數(shù)現(xiàn)在已經(jīng)可以通過參數(shù)來指明編碼。
減輕痛苦
好,那么如何來減少這些痛苦?好消息是減輕痛苦的規(guī)則非常簡單,在Python 2和 Python 3中都比較適用。
正如我們在事實一中所看到的,在你的程序中進(jìn)進(jìn)出出的只有 bytes, 但是在你的程序中你不必處理所有的 bytes。最好的策略是將輸入的 bytes 馬上解碼成 unicode。你在程序中均使用 unicode ,當(dāng)在進(jìn)行輸出的時候,盡早將之編碼成 bytes 。
制造一個 Unicode 三明治, bytes 在外, Unicode 在內(nèi)。
要記著,有時候一些庫將會幫助你完成類似的事情。一些庫可能讓你輸入 unicode,輸出 unicode,它會幫你完成轉(zhuǎn)換的功能。比如 Django 在它的 json 模塊中提供 Unicode。
第二條規(guī)則是:你需要知道你現(xiàn)在處理的是哪種類型的數(shù)據(jù),在你的程序中任何一個位置,你需要知道你處理的是 byte 串還是一個 unicode 串。它不能是一種猜測,而應(yīng)該被設(shè)計好。
另外,如果你有一個 byte 串的話,如果你想對它進(jìn)行處理。那么你應(yīng)該知道它是怎樣的編碼。
在對你的代碼進(jìn)行 debug 的時候,不能僅僅將之打印出來來看它的類型。你應(yīng)該查看它的 type ,或者查看它 repr 之后的值來查看你的數(shù)據(jù)到底是什么類型。
我曾經(jīng)說過,你應(yīng)該了解你的 byte 字符串的編碼類型。好這里要我講事實四:你不能通過檢查它來判斷這個字符串編碼的類型。你應(yīng)該通過其他途徑來了解。比如很多協(xié)議中將會指明編碼類型。這里我們給出 HTTP, HTML, XML, Python 源文件中的例子。你也可以通過預(yù)先的指定來了解編碼。比如數(shù)據(jù)源碼中可能會指明編碼。
有一些方式可以來猜測一些 bytes 的編碼類型。但是僅僅是猜測。能夠確定的唯一方式是通過其他方式。
這里是給出一些怪異的字符的編碼猜測。我們用UTF-8 便民店的一些字符,被不同的解碼方式解碼之后的輸出。你可以看見。有時候用不正確的解碼方式解碼可能會輸出正確,但是會輸出錯誤的字符。你的程序不能告訴你這些解析錯誤了。只有當(dāng)用戶察覺到的時候你才會發(fā)現(xiàn)錯誤。
這是事實四的一個好例子:同樣的 bytes 流通過不同的解碼器是可以解碼的。而 bytes 本身不能指明它自己用的哪種編碼方式。
順便說一下,這些垃圾信息的顯示只遵循一個規(guī)則,那就是亂碼。
不幸的是,bytes 流會根據(jù)自己的來源不同而進(jìn)行不同的編碼,有時候我們指明的編碼方式可能是錯誤的。比如你有可能將一個 HTML 從網(wǎng)上抓取下來,HTTP 頭中指明編碼方式是 8859-1, 然而實際上的編碼確是 UTF-8。
在一些情況下編碼方式的不匹配可能會產(chǎn)生亂碼,而有些時候,則會產(chǎn)生 UnicodeError。
不用說。你應(yīng)該測試你的 Unicode 支持。為了這樣。你首先應(yīng)該在你的代碼中首先去先把 Unicode 來提取出。如果你只會說英語,這可能會有些困難。因為有些 Unicode 數(shù)據(jù)會比較難以讀。幸運的是,大部分時候一些復(fù)雜結(jié)構(gòu)的 Unicode 字符串還是比較具有可讀性的。
這里是一個例子。ASCII 文本中可以讀的文本,和倒置的文本。這些文本的一些有時候是一些青年人會粘貼到社交網(wǎng)絡(luò)中。
根據(jù)你的程序,你有可能在 Unicode 的道路中越挖越深。還有很多很多的細(xì)節(jié)我這里沒有解釋清楚。可以被涉及到。我們稱之為事實五。因為你不必去對此了解太詳細(xì)。
復(fù)習(xí)一下,我們有五個不可忽視的事實:
程序中所有的輸入和輸出均為 byte
世界上的文本需要比 256 更多的符號來表現(xiàn)
你的程序必須處理 byte 和 unicode
byte 流中不會包含編碼信息
指明的編碼有可能是錯誤的
這是你在編程中保持 Unicode 清潔的三個建議:
Unicode 三明治:盡可能的讓你程序處理的文本都為 Unicode 。
了解你的字符串。你應(yīng)該知道你的程序中,哪些是 unicode, 哪些是 byte, 對于這些 byte 串,你應(yīng)該知道,他們的編碼是什么。
測試 Unicode 支持。使用一些奇怪的符號來測試你是否已經(jīng)做到了以上幾點。
如果你遵循以上建議的話,你將會寫出對 Unicode 支持很好的代碼。不管 Unicode 中有多么不規(guī)整的編碼你的程序也不會掛掉。
一些其他你可能需要的資源
Joel Spolsky 編寫的 The Absolute Minimum Every Software Developer Absolutely, Positively Must Know About Unicode and Character Sets (No Excuses!) 概括了 Unicode 的工作方式和原因。雖然沒有 Python 的內(nèi)容,但是比我解釋的詳細(xì)多了!
如果你需要處理一些語義上的 Unicode 字符問題。那么 unicodedata module 也許會對你有些幫助。
如果你希望找一些 Unicode 來測試的話,網(wǎng)上各種的 編碼文本計算器 會對你很有幫助。
文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請注明本文地址:http://specialneedsforspecialkids.com/yun/42330.html
摘要:搭建多頁面應(yīng)用在往下看之前請確保先上個涼的吃著目錄結(jié)構(gòu)編譯結(jié)果配置文件腳本存放處項目開發(fā)中一些常用的方法主要存放和請求有關(guān)的靜態(tài)文件模版文件項目開發(fā)中一些常用的方法其實我覺得可以和放在一塊,但是個人習(xí)慣還是分開啦開始擼代碼如何創(chuàng)建多頁面應(yīng)用 webpack4 搭建 react 多頁面應(yīng)用 在往下看之前請確保nodejs > 8.X 先上個涼的吃著 目錄結(jié)構(gòu) . ├── dist ...
摘要:摘要通過阿里云容器服務(wù)開啟你的數(shù)據(jù)服務(wù)之旅一云上運維自建數(shù)據(jù)庫之痛,使用容器服務(wù)自動恢復(fù)數(shù)據(jù)庫實例概述本文為大家介紹一種容器化的數(shù)據(jù)服務(wù),通過使用云盤自動掛載實現(xiàn)的塊存儲來做到數(shù)據(jù)庫的免運維恢復(fù)。 摘要: 通過阿里云Kubernetes容器服務(wù),開啟你的數(shù)據(jù)服務(wù)之旅 (一)云上運維自建數(shù)據(jù)庫之痛,使用容器服務(wù)自動恢復(fù)數(shù)據(jù)庫postgresql實例 概述 本文為大家介紹一種容器化的數(shù)據(jù)服...
摘要:所以,解決方案是強(qiáng)制要求從整個項目的頂層用來設(shè)置端正的路徑。這個做法是官方推薦的,也是合邏輯的,即一個完整的項目運行就應(yīng)當(dāng)以項目為入口來運行所有的子或子。經(jīng)過不斷的實踐,發(fā)現(xiàn)他們大都沒說清楚上下文,甚至沒有告訴完整的解決方案。 參考Python官方:Packages?參考:Python相對導(dǎo)入一處不解參考:使用相對路徑名導(dǎo)入包中子模塊 理解Package Python里,就像所有的.p...
閱讀 2796·2021-11-16 11:44
閱讀 969·2021-10-09 09:58
閱讀 4489·2021-09-24 09:48
閱讀 4250·2021-09-23 11:56
閱讀 2407·2021-09-22 15:48
閱讀 1892·2021-09-07 10:07
閱讀 3204·2021-08-31 09:46
閱讀 504·2019-08-30 15:56