国产xxxx99真实实拍_久久不雅视频_高清韩国a级特黄毛片_嗯老师别我我受不了了小说

資訊專欄INFORMATION COLUMN

unicode和utf8 —— 從一個遍歷文件名的腳本,談談對Python2和Python3中字符編

寵來也 / 1526人閱讀

摘要:如果傳一個中文,下和下編碼分別是和,可以自己用打印看看文件中寫死,本來理解是跟這個文件本身編碼有關,但文件編碼同樣是的情況下,下打印了的超集,下仍然是。

對編碼問題一直一知半解,之前也是得過且過,正好有個同事要我幫忙寫個腳本,涉及這方面的問題,借這個契機研究了一下.

先貼幾篇比較好的:

1.阮老師的上古文章(07年…),雖然古老但對理解幫助很大,從最基礎講起,邏輯清晰易理解. (ps: 阮老師的博客都有此特點, 在這里推薦一波, 從js到linux, 精通前后端, 是可以當文檔看的博客): http://www.ruanyifeng.com/blo...

2.最好看了上一篇再看這篇(解釋了py2中為什么不能用 setdefaultencoding): https://blog.ernest.me/post/p...

3.關于UnicodeDecodeError: https://stackoverflow.com/que...

以及Python3的官方文檔:https://docs.python.org/relea...

=============================================================================
建議以上幾篇理解的差不多后再看正文:

簡單說一下:
2.x中的編碼概念是不夠清晰的,str類型的對象會被賦予默認編碼,且既可以對其編碼又可以對其解碼(單這一點就足夠造成很多混亂…),而我們在代碼中常直接使用帶編碼的str進行os庫相關的操作,就容易導致很多問題。對于python內部來說,解釋器處理操作系統的文件目錄相關的東西時,必須使用unicode。新手如果要讀取文件名并進行一些處理時,經常遇到亂碼,以及windows和linux下效果不同的問題。另外一個主要場景就是stream,流處理,這個就是寫文件或者前后端通信之類,這個相對前面問題來說其實還算好處理的。然后還有字符串拼接。

3.x去掉了 unicode類型 和 unicode()函數,(也就沒有u"xxx"這種寫法了),區分出str類型和bytes類型,而且str不再同時有encodedecode方法,bytes只有decodestr只有encode
3.x中,沒有了unicode這個類型,可以理解為str成為了unicode類型,"All text is Unicode"。而帶編碼的字符串則由bytes類型來處理。但也不能簡單地理解為3.x的str和bytes分別對應2.x的unicode和str。

所以2.x處理字符串原則其實也很簡單,就是把str當成bytes,內部只用unicode,外部進的和出的都編碼成str。

這里可能有個疑問就是,按之前的理解(假設已經讀了第1篇)unicode是編碼規則,但不是存儲方式,uft8才是它的實現,才能用來存儲,那么如果python內部是用unicode方式處理文本,在內存中python解釋器如何正確讀取字符呢?這里要理解清楚所謂實現,其實多的就是一個字節數的信息,unicode和utf8本質上都是一串0和1,只是缺一個字節數量的區分,即,從信息量上來說: unicode + 自身長度 = utf8。這樣,在python解釋器的處理過程中,python自然有辦法用自己的標記來正確讀寫“自身長度”這個信息,因為這里不需要和外界交互,不需要類似utf8這樣的約定規則,自己內部能正確獲取信息即可。utf8是為了省硬盤空間,內存中不太需要這樣的東西。(這段屬于個人想當然的理解,僅供參考)

重點,重點,重點,貼一下py2中處理編碼的原則(摘自上面第3篇),也就是我上面那句總結的完整版,如果你理解了為什么有這個原則說明差不多理解了py2的編碼:

·所有 text string 都應該是 unicode 類型,而不是 str,如果你在操作 text,而類型卻是 str,那就是在制造 bug。
·在需要轉換的時候,顯式轉換。從字節解碼成文本,用 var.decode(encoding),從文本編碼成字節,用 var.encode(encoding)。
·從外部讀取數據時,默認它是字節,然后 decode 成需要的文本;同樣的,當需要向外部發送文本時,encode 成字節再發送。

除了上面幾篇,百度還有無數其他的講解,本篇就不再贅述原理之類的,上腳本講下實際應用,腳本功能是遞歸遍歷目錄下所有文件:

#-*- coding:utf-8 -*-
"""
Description :  
遞歸遍歷目錄下所有文件(排除目錄),并逐行寫入到指定文件中。
可以分別用py2或py3來執行,結果相同。
可以不帶參數,或者 python xxxx  

主要干兩件事:
第一步,把文件路徑解碼成unicode,傳給os用來遍歷 (僅py2)
第二步,把文件名編碼后寫入文件
這樣正好覆蓋了上面提到的兩個主要場景。
"""

""" 
Python2: str -> (decode) -> unicode -> (encode) -> str
Python3: bytes -> (decode) -> str(unicode) -> (encode) -> bytes 
"""

import sys
import os

try:
    PATH = sys.argv[1]
except IndexError:
    # 在這里寫一個你能找到的名字最亂,里面文件名最雜的文件夾
    PATH = r"./"  # raw string, 表示不進行轉義, 如果復制一個帶反斜杠后面帶數字或字母的路徑, 不加上這個r就會出錯
    
try:
    WRITE_PATH = sys.argv[2]
except IndexError:
    WRITE_PATH = "abc"   # 指定要寫入的文件名


PY2 = sys.version.startswith("2")


if PY2:
    # 不理解編碼的人經常用這個當做萬能藥,這個確實也有用,但嚴重不推薦使用,見第3篇
    # import sys
    # reload(sys)  
    # sys.setdefaultencoding("utf8")
    # PATH = PATH.decode()  # 這樣就默認以utf8解碼,由于上面的代碼導致傳進來的PATH會被默認編碼為utf8


    # 記住原則,在python內處理文本字符串,永遠保證是unicode類型,所以這里要進行解碼。關于"ignore"參數見第4篇
    # 這里PATH不帶中文時,無論哪種都會默認為ascii編碼,帶其他非ascii文字時,根據來源如果是:
    # 1. sys.argv傳入,那么PATH的編碼跟操作系統有關。如果傳一個中文,windows下和linux下編碼分別是ISO-8859-1和utf8,可以自己用chardet打印看看
    # 2. 文件中寫死,本來理解是跟這個文件本身編碼有關,但文件編碼同樣是utf8的情況下,windows下打印了Windows-1252(ISO-8859-1的超集),linux下仍然是utf8。所以還是跟操作系統有關
    # 這里默認在linux系統下執行,所以直接用utf8解了,如果要兼容,可以用chardet獲取編碼類型后指定進行解碼
    PATH = PATH.decode("utf8", "ignore")

# if PY3,無論傳入還是寫死PATH都將會是```str```類型,當然也就不需要也不能進行解碼啦


def getf(path):
    l = []
    res = os.listdir(path)
    for each in res:
        subpath = os.path.join(path, each)
        if os.path.isdir(subpath):
            l.extend(getf(subpath))
        else:
            l.append(each)

    return l

res = getf(PATH)



if PY2:
    # Python2, 由于py2中概念的模糊, 可以直接用"w"打開去寫,而不需要"wb"
    # 不過不編碼成utf8的話也是會拋UnicodeDecodeError的,寫文件需要編碼這個原則py2還是有的。可以檢查一下 "%s
" % each 的類型毫無疑問是unicode
    with open(WRITE_PATH, "w") as f:
        for each in res:
            f.write(("%s
" % each).encode("utf8"))

else:
    # Python3, 可以用w打開然后不編碼直接寫string(即unicode),也是可以成功寫的,不過那樣結果是非ascii都亂碼。
    # 而編了碼就轉為了bytes類型,所以Python3想正確實現就必須用二進制方式打開 (wb)
    # 如果打開方式和寫入類型不對應,會拋TypeError,很明確
    with open(WRITE_PATH, "wb") as f:
        for each in res:
            f.write(("%s
" % each).encode("utf8"))

總結下代碼,首先可以看到py3是沒毛病的,對編碼的操作概念清晰,沒有任何困擾。

py2這塊確實有硬傷,雖然很多時候也無所謂,但在要嚴謹或者專門處理編碼的代碼中,一定要記住開頭貼的原則。

關于setdefaultencoding,除非實在不重要的場景,又需要臨時簡單解決,可以湊合一下,普通場景不建議用.
原因第3篇解釋得很清楚。另附官方文檔的說明如下:
set the current default string encoding used by the Unicode implementation. If name does not match any available encoding, LookupError is raised. This function is only intended to be used by the site module implementation and, where needed, by sitecustomize. Once used by the site module, it is removed from the sys module’s namespace.

文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。

轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/41384.html

相關文章

  • 聊聊Python 3 字符串:str bytes 區別

    摘要:的字符串有兩種和,的字符串也有兩種和。不同字符的不同表現,讓的和顯得撲朔迷離。在中,嚴格區分了和,不同類型之間操作就會拋出的異常。和之間的轉換一圖勝千言和的相互轉換指的是具體的編碼規則的名稱,對于中文來說,它可以是這些值等等。 Python2的字符串有兩種:str 和 unicode,Python3的字符串也有兩種:str 和 bytes。Python2 的 str 相當于 Pytho...

    AWang 評論0 收藏0
  • Python學習之路23-文本字節序列

    摘要:字符編碼表,碼位碼元將編碼字符集中的碼位轉換成有限比特長度的整型值的序列。字符編碼方案,碼元序列化也稱為常說的序列化。每個字節里的二進制數就是字節序列。另一個情況則是壓縮字節序列的值,如或進程長度編碼等無損壓縮技術。 《流暢的Python》筆記。本篇主要講述不同編碼之間的轉換問題,比較繁雜,如果平時處理文本不多,或者語言比較單一,沒有多語言文本處理的需求,則可以略過此篇。 1. 前言 ...

    anRui 評論0 收藏0
  • 關于python解碼(decode, encode)

    摘要:,,等屬于不同的字符集,轉換編碼就是在它們中的任意兩者間進行。一般個人用的電腦上控制臺基本上都是編碼的,但運維的機器上基本全是,中文的時候就會有酸爽的問題。 總結總結,本文僅適用于python2.x 默認編碼與開頭聲明 首先是開頭的地方聲明編碼 # coding: utf8 這個東西的用處是聲明文件編碼為utf8(要寫在前兩行內),不然文件里如果有中文,比如 a = 美麗 b = u美...

    shusen 評論0 收藏0
  • Python入門-基本語法1

    摘要:根據有效范圍作用域分為全局變量和局部變量。類型以開頭標識類型以開頭標識類型以進制的字節碼表示,實際上是一個字節串,回應了它的另一個名字。 < 返回索引頁 基本語法 Hello World 代碼注釋 關鍵字 數據類型 變量、常量 變量 變量賦值 變量命名 變量的作用域 常量 字符串與編碼 字符轉義 字符編碼 字符串操作 運算符與表達式 運算符 表達式 ...

    ingood 評論0 收藏0
  • Python知識點整理(day1)

    摘要:上一步中執行時,明確的指出腳本由解釋器來執行。為了表示更多的中文漢字有了,但是,中華文化博大精深,發現不夠用,因此有了對的擴展即。但是,用編碼對于英文只占一個字節,,一個中文漢字在卻占三個字節可能是中國人有錢啊,我大天朝。 簡介: Python是一種解釋型語言,需要解釋器來執行。可以通過在IDLE下執行,也可以在文本文件里寫入代碼,然后將該文件命名為xx.py 然后在Windows下可...

    Luosunce 評論0 收藏0

發表評論

0條評論

寵來也

|高級講師

TA的文章

閱讀更多
最新活動
閱讀需要支付1元查看
<