19.python的編碼問題

来源:http://www.cnblogs.com/scolia/archive/2016/06/03/5554768.html
-Advertisement-
Play Games

在正式說明之前,先給大家一個參考資料:戳這裡 文章的內容參考了這篇資料,並加以總結,為了避免我總結的不夠完善,或者說出現什麼錯誤的地方,有疑問的地方大家可以看看上面那篇文章。 以下說明是針對於python2.x版本,因為在python3.x中預設使用的是Unicode。 下麵開始講python中的編 ...


  在正式說明之前,先給大家一個參考資料:戳這裡

  文章的內容參考了這篇資料,並加以總結,為了避免我總結的不夠完善,或者說出現什麼錯誤的地方,有疑問的地方大家可以看看上面那篇文章。

  以下說明是針對於python2.x版本,因為在python3.x中預設使用的是Unicode。

  下麵開始講python中的編碼問題,首先,我們看看編碼有哪些。

  1. ASCII

  ASCII是用一個位元組表示字元,而一個位元組由八位二進位組成,所以能產生2**8=256種變化,在電腦剛誕生的年代,用來表示大小寫的26個英文字母,外加一些符號之類的還是綽綽有餘的。這也是python2.x中預設使用的編碼,所以在python2.x中預設不能使用中文,除非使用編碼聲明。

  2. MBCS

  隨著時代的發展,ASCII就太夠用了,電腦不能只顯示英文吧,那樣實在太low。此時,大家看到ASCII碼中還有沒用完的,所以都想占用剩下的部分,但是剩下的部分還是不夠,例如我們中文那麼多肯定是不夠用的,所以此時又擴展了一下,一個位元組不行,我就用兩個。而又為了相容ASCII碼,有定義了這樣一套規則:如果第一個位元組是\x80以下,則仍然表示ASCII字元;而如果是\x80以上,則跟下一個位元組一起(共兩個位元組)表示一個字元,然後跳過下一個位元組,繼續往下判斷。例如GB...和BIG...之類的都遵循這樣的規則。

  但是,這樣還是實在太亂了,此時IBM跳了出來,大喊一聲:這些東西都要統一進行管理!!所以弄出了代碼頁的概念,將這些字元集都收錄了起來,併進行了分頁,而這些分頁的總稱就叫MBCS,例如GBK在936頁,所以又叫cp936。而大家都是使用的雙位元組,所以也稱為DBCS。

  但很明顯,MBCS裡面收集和各樣的字元集,但是你不能說你要使用MBCS這個字元集編碼,裡面存了怎麼多種,到底是要用哪種,你不說清楚我總不能隨機給你一種吧。所以必須要進行指定,但是這個工作已經由操作系統自己完成了(linux不支持),而操作系統有時根據地區的不同而選擇的。例如簡體中文版的,就選GBK,其他國家的又會有不同,具體按版本而定。所以,一旦在python的編碼聲明中使用MBCS/BDCS,在進行過系統或跨地區運行的時候,報錯也是在所難免的。所以編碼聲明中一定要具體的指定,例如我們常用的utf-8,這樣就不會因為系統和地區的差異而造成各種編碼的錯誤。

  在windows中,微軟又為它起了個別名,叫ANSI,其實就是MBSC,大家知道就好了。

  3.Unicode

  雖然MBSC一定程度上解決了編碼混亂的問題,但還是特點的編碼只能顯示特點的字元。這樣要開發一種適配多國語言的程式就變得非常困難,此時人們在想,有沒有一種編碼能搞到所以的字元。大家研究了一番之後,Unicode就此誕生。乾脆大家都不要在ASCII上拓展來拓展去,搞得各種版本如此混亂。以後大家都用兩個位元組保存算了,這樣就有了256*256=65536種字元可以表示了,總歸是夠用了吧。這就是UCS-2標準了。後來還有人說不夠用的,那麼乾脆翻一倍,用四個位元組表示,256**4=4294967296,就算將來表示外星文字也能撐一段時間了吧。當然現在常用的還是UCS-2標準的。

  UCS(Unicode Character Set)還僅僅是字元對應碼位的一張表而已(也就是表示位元組),比如"漢"這個字的碼位是6C49。字元具體如何傳輸和儲存則是由UTF(UCS Transformation Format)來負責(也就是保存位元組)。(註意:表示位元組≠保存位元組,也就是雖然我用了2個位元組表示字元,但是我保存的時候不一定就直接保存用來表示的那個位元組)

  剛開始都是直接使用UCS的碼位來保存,這就是UTF-16,比如,"漢"直接使用\x6C\x49保存(UTF-16-BE),或是倒過來使用\x49\x6C保存(UTF-16-LE)。但美國佬後來不願意了,我原來用ASCII只有1個位元組就能搞到,現在卻要兩個位元組,足足長了一倍呀。一倍是什麼概念,四捨五入那是將近一個億呀真當我磁碟空間不用錢呀,為了滿足這個述求,就誕生了UTF-8。

  UTF-8是一種很彆扭的編碼,具體表現在他是變長的,並且相容ASCII,ASCII字元使用1位元組表示。但有得必有失,在UTF-8中,東亞的文字是用三個位元組表示的,包括中文,一些不常用的字元更是用四個位元組表示。於是別的國家保存的成本變高了,而美國佬卻變低了。又再次坑了別人,滿足了自己。但是沒辦法,誰叫人家是電腦界的老大呢?

 

什麼是BOM

   當一個文本編輯要打開一個文件時,它表示懵逼了。世間編碼如此之多,我究竟要用什麼哪種編碼去解碼呀?你總得告訴我吧!

  此時,UTF就進入了BOM來表示編碼。所謂的BOM就是文件使用編碼的標識符,就和python的編碼聲明一樣,告訴文本編輯器我用的是什麼編碼,下麵的你都用那個編碼去解碼就行。

  同樣的,只有文本編輯器在文件開頭的地方讀到了關於BOM的描述,就能夠進行正確的界面了。

  下麵是一些BOM的總結:

  BOM_UTF8 '\xef\xbb\xbf'
  BOM_UTF16_LE '\xff\xfe'
  BOM_UTF16_BE '\xfe\xff'

  同樣了,為了我們自己編輯的文件的編碼也能被正確識別,我們也要寫入BOM,一般由編輯器完成。但不寫也可以,只有在打開文件的時候自己手動選擇用什麼去解碼也是可以的。

  但是,還有一種叫UTF-8無BOM模式的,這又是什麼鬼。

  因為UTF-8實在太流行了,所以文本編輯器預設會首先用UTF-8進行解碼。即使是保存時預設使用ANSI(MBCS)的記事本,在讀取文件時也是先使用UTF-8測試編碼,如果可以成功解碼,則使用UTF-8解碼。記事本這個彆扭的做法造成了一個BUG:如果你新建文本文件並輸入"奼塧"然後使用ANSI(MBCS)保存,再打開就會變成"漢a"。)

  下用一幅圖來總結:

  此時,有些人會在MBCS和UCS-2之間迷糊,大家都是兩個位元組表示,又有什麼不同?

  MBCS是各自拓展的,有就是說很可能相同的二進位表示MBCS會出現不同的結果,而Unicode是統一拓展,保證了每種二進位表示都對應唯一一個字元,保證了唯一性,也就提高了相容能力。

 


   

  ok,在講完字元編碼的問題之後,現在再來看一下:

   # coding:gbk 和 # coding= utf-8 之類的編碼聲明對python而言到底意味著什麼。

  這裡插播一個小技巧:

   # coding : utf-8 或者這樣 # coding = utf-8 的聲明方式是會報錯的,這裡並不是說是特點的=或者:的問題,而是空格的問題,在coding和符號之間是不能有空格的,但在符號和utf-8之類的編碼名稱間是運行0個或多個空格的,#和coding間也是運行0個或多個空格的。我也不知道為什麼,但實際就是報錯了。

#! /usr/bin/env python
#coding = utf-8
print '中文'

 

  這裡coding和=號一個空格:

  報錯了。

#! /usr/bin/env python
#coding= utf-8
print '中文'

  coding和=之間沒空格:

  正常執行。

  不清楚是我IDE的問題還是python本來的語法是這樣規定的,但其實很少有地方談及這個地方的語法,所以這裡提及一下,最後自己實驗一下。

   # -*- coding: utf-8 -*- 的寫法也是一樣的。

 

  好了,一下進入正題:

#! /usr/bin/env python
# coding= utf-8
print '中文'
print str('中文')
print repr('中文')
print repr(u'中文')

 

  這裡順便解釋一下str()函數和repr()函數在創建或轉換字元串上的區別,str()得到是一個對人類可讀性比較好的字元串,而print也是預設調用這個函數的。而repr()是創建或轉換字元串時,得到是對機器可讀性更好的字元串,就是這裡得到是其編碼。

  下麵是另一種編碼的輸出:

#! /usr/bin/env python
# coding= gbk
print '中文'
print str('中文')
print repr('中文')
print repr(u'中文')

 

 

  前面兩個是亂碼,不過這裡是我IDE的問題,我的IDE預設是用UTF-8的。

您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • C++這門語言從誕生到今天已經經歷了將近30個年頭。不可否認,它的學習難度都比其它語言較高。而它的學習難度,主要來自於它的複雜性。現在C++的使用範圍比以前已經少了很多,java、C#、python等語言在很多方面已經可以代替C++。但是也有很多地方是其他語言完全無法替代的,主要集中在需要運行效率比 ...
  • Ok,我又來寫SOLR的內容了,昨天做了修改和增加的增量索引,今天來說說關於刪除的增量索引以及定時更新增量索引,廢話不多說,下麵進入正文。 一、增量索引之刪除 昨天已經說過,增量索引其實就是SOLR對上次做過(增量或者全量)索引之後到這次做索引之間的這段時間資料庫發生變化的數據進行創建索引,昨天我們 ...
  • 1. D:\AWS_workspace\DAAS_Go>go get -u -ldflags -H=windowsgui github.com/nsf/gocode 2. Then gocode.exe will be installed in "D:\AWS_workspace\DAAS_Go\b ...
  • http://blog.csdn.net/hengyunabc/article/details/7371446 本文章地址:http://blog.csdn.net/hengyunabc/article/details/7371446 2012-03-31:新版的goclipse改進很大,本文有些內 ...
  • 最近想學習下Go語言,先從最基本的Hello Go開始,搭建Go開發環境 一、下載Go包 由於Go官網國內訪問經常有問題,可以從國內的鏡像下載: http://www.golangtc.com/ 二、配置環境變數 1、將Go的壓縮包解壓到任意目錄,我的為D:\SDE\go 2、 配置GoRoot路徑 ...
  • http://www.cnblogs.com/qgymje/p/3912259.html 這篇原來是給公司里使用go開發的交流用的,主要是工具的安裝,用markdown寫的,發佈了內部gitlab上,倉促發佈到blog上面,也沒改啥格式,現在整理一下,然後增加一點說明 基礎開發工具 sublime ...
  • http://www.distilnetworks.com/setup-go-golang-ide-for-mac-os-x/#.V1Byrf50yM8 Programming in Go (Golang) – Setting up a Mac OS X Development Environmen ...
  • Spring Mvc簡介: Spring Web MVC是一種基於Java的實現了Web MVC設計模式的請求驅動類型的輕量級Web框架,即使用了MVC架構模式的思想,將web層進行職責解耦,基於請求驅動指的就是使用請求-響應模型,框架的目的就是幫助我們簡化開發,Spring Web MVC也是要簡 ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...