天天看點

PyQt的QString和python的string的差別

python的string和PyQt的QString的差別 python string和PyQt的QString的差別 以下在Python2.6和PyQt4.4.4 for Python2,6環境下讨論: Python中有兩種有關字元的類型:Python string object和Python Unicode object。主要使用Python string object進行資料輸入

  

python string和PyQt的QString的差別

以下在 Python2.6和PyQt4.4.4 for Python2,6環境下讨論:

Python中有兩種有關字元的類型:Python string object和Python Unicode object。主要使用Python string object進行資料輸入輸出。

PyQt中與之相對應的字元有關類型是:QByteArray和QString。主要使用QString操作資料。

1. Python和PyQt中的類型對應

注意是類型相似,不是相等。

需要先了解編碼:ascii、gb2312、big5,這些是各國自己文字不同的編碼;unicode,國際通用編碼,就是窮盡這個世界上所有的文字,給 每個文字編一個,又分utf-8方案--最常使用的128個英文字母用一個位元組來表示,而中文使用三個位元組來表示,utf-16方案--其中英文和中文都 使用兩個位元組來表示,而其它字元采用四個位元組,utf-32方案--所有的文字都用四個位元組來表示。

unicode就可用來作為各種獨立編碼如ascii、gb2312、big5的轉換中介。

Python中gkb == gb2312。

1)Python string object可以了解為一個接一個位元組(byte,8位)的位元組組,至于表示什麼編碼,與表示文字有關,如:"python string","中文"。注意它是有不同編碼區分的!

PyQt中與之相當的是QByteArray,注意不是QString!

A built-in string object (plain or Unicode) is a sequence of characters used to store and represent text-based information (plain strings are also sometimes used to store and represent arbitrary sequences of binary bytes). (摘自《Python in a NutShell》)

QByteArray can be used to store both raw bytes (including '0's) and traditional 8-bit '0'-terminated.(摘自《PyQt手冊》)

2)Python Unicode object可以了解為固定使用utf-16編碼的位元組組,其中英文和中文都使用兩個位元組(16位)來表示,如:u"Python Unicode object"、u"中文"。

PyQt中與之對應的就是QString了。

Unicode string literals have the same syntax as other string literals, with a u or U immediately before the leading quote. (摘自《Python in a NutShell》)

Qt also provides the QString class to store string data. It stores 16-bit Unicode characters, making it easy to store non-ASCII/non-Latin-1 characters in your application.(摘自《PyQt手冊》)

QString stores a string of 16-bit QChars, where each QChar corresponds one Unicode 4.0 character.(摘自《PyQt手冊》)

2. PyQt内部類型轉換

QString有 toAscii()、toUtf8()函數轉換為QByteArray類型,(這個基本不用,因為很少直接用QByteArray類型)有 __init__ (self, QByteArray a)函數将QByteArray類型轉為QString。

3. Python string object和Python Unicode object互相轉換

1)Python string object是原始編碼是有區分的,通過 decode('原始編碼') 函數解碼得到通用utf16編碼即Python Unicode object。

>>>"python string".decode('ascii')

或者

>>>"python string".decode()

得到 u"python string"

因為預設按ascii解碼。

>>>"中文".decode('gbk')

得到 u"u4e2du6587" ,列印出來就是 中文 二字。(注意結果是2位元組一組,共兩組,對應兩個漢字)

又:"python string".decode('gkb') ,即按漢字來解碼,也可以得到 u"python string",因為gbk編碼也支援英文字母;

但是"中文".decode('ascii') 即按ascii解碼是錯誤的,因為ascii編碼不支援漢字!

>>> "dfdf".decode()

u'dfdf'

>>> "dfdf".decode("ascii")

u'dfdf'

>>> "dfdf".decode("gbk")

u'dfdf'

>>> "中文".decode("gbk")

u'u4e2du6587'

>>>print "中文".decode("gbk")

中文

>>> "中文".decode("gb2312")

u'u4e2du6587'

>>> "中文".decode("ascii")

Traceback (most recent call last):

File "<interactive input>", line 1, in <module>

UnicodeDecodeError: 'ascii' codec can't decode byte 0xd6 in position 0: ordinal not in range(128)

2)Python Unicode object原始編碼固定是utf16,通過 encode('目的編碼') 編碼來得到Python string object。

>>>u"unicode string".encode()

或者

>>>u"unicode string".encode('ascii')

得到

'unicode string',預設目的編碼為ascii。

>>>u"中文".encode("gbk")

得到'xd4xd0xcexc4',列印出來就是 中文。(注意結果是1位元組一組,共4組)

>>> u"sdff".encode()

'sdff'

>>> u"sdff".encode('ascii')

'sdff'

>>> u"sdff".encode('gbk')

'sdff'

>>> u"sdff".encode('gb2312')

'sdff'

>>> u"中文".encode('gbk')

'xd6xd0xcexc4'

>>> print u"中文".encode('gbk')

中文

>>> u"中文".encode('ascii')

Traceback (most recent call last):

File "<stdin>", line 1, in <module>

UnicodeEncodeError: 'ascii' codec can't encode characters in position 0-1: ordin

al not in range(128)

注意:執行>>> u"中文".encode('gbk')指令需要你的IDE支援gbk編碼,在官方shell下執行肯定沒問題,但如果你的IDE比如PyWin中文輸入 異常,則可能報錯。

4. Python string object和Python Unicode object向QString的轉換。

Qt一般不直接操作QByteArray,隻需關注Python string object和Python Unicode object向QString的轉換。

很多關于PyQt4的英文書籍說:PyQt函數需要QString參數的地方都可以直接用Python string object或者Python Unicode object,如果非要轉換可以直接用QtCore.QString()構造。比如《GUI Programming with PyQt》,再如《PyQt手冊》:

Whenever PyQt expects a QString as a function argument, a Python string object or a Python Unicode object can be provided instead, and PyQt will do the necessary conversion automatically.

You may also manually convert Python string and Unicode objects to QString instances by using the QString constructor as demonstrated in the following code fragment:

qs1 = QtCore.QString("Converted Python string object")

qs2 = QtCore.QString(u"Converted Python Unicode object")

但可惜這隻适用于英文 即ascii編碼,對于中文則行不通!

直接的 QString:

>>> QtCore.QString('中文')

PyQt4.QtCore.QString(u'xd6xd0xcexc4')

>>> print QtCore.QString('中文')

Traceback (most recent call last):

File "<stdin>", line 1, in <module>

UnicodeEncodeError: 'ascii' codec can't encode characters in position 0-3: ordin

al not in range(128)

>>>

>>> QtCore.QString(u'中文')

PyQt4.QtCore.QString(u'u4e2du6587')

>>> print QtCore.QString(u'中文')

Traceback (most recent call last):

File "<stdin>", line 1, in <module>

UnicodeEncodeError: 'ascii' codec can't encode characters in position 0-1: ordin

al not in range(128)

>>>

因為它們都是預設按ascii編碼轉換!

GUI程式設計:

可以建立一個QTextEdit對象myTextEdit, 檢驗:

myTextEdit.append("中文")

或者

myTextEdit.append(u"中文")

或者

myTextEdit.append(QtCore.QString('中文'))

或者

myTextEdit.append(QtCore.QString(u'中文'))

你會發現顯示都是亂碼...因為它們都是預設按ascii編碼進行内部轉換得到QString相應utf16編碼的。

解決方法是:

利用unicode()函數顯示指定gb2312編碼進行中文編碼轉換,轉換後的Python Unicode object則是可以直接作為QString參數代入用的:

>>> unicode('中文', 'gb2312', 'ignore')

u'u4e2du6587'

>>> print unicode('中文', 'gb2312', 'ignore')

中文

>>>

myTextEdit.append(unicode(' 中文', 'gb2312', 'ignore'))

#用以替代myTextEdit.append(u"中文")

或者多此一舉下:

myTextEdit.append(QtCore.QString(unicode('中文', 'gb2312', 'ignore')))

#用以替代myTextEdit.append(QtCore.QString(u'中文'))

5. QString向Python string object和Python Unicode object的轉換。

Python中需要用Python string object和Python Unicode object的地方可就不一定可以直接用QString了!!!

QString向Python string object轉換可以了解,因為編碼不同。

QString向Python Unicode object的轉換?需要轉換嗎?不都是utf16編碼嗎?

QString是tuf16編碼,但是它的實作并非Python Unicode object那樣直接的utf16碼,而實際是一個QChar串,每個QChar才對應unicode符,是以地位相當但并不相同。

許多英文書籍寫到:可以使用str()函數直接将QString轉換為Python string object,可以使用unicode()直接将QString轉換為Python Unicode object。如《PyQt手冊》:

In order to convert a QString to a Python string object use the Python str() builtin. Applying str() to a null QString and an empty QString both result in an empty Python string object.

In order to convert a QString to a Python Unicode object use the Python unicode() builtin. Applying unicode() to a null QString and an empty QString both result in an empty Python Unicode object.

但同樣隻适用于英文, 具體見下面分别分析。

1)QString向Python Unicode object的轉換。

>>> from PyQt4 import QtGui, QtCore

>>> unicode(QtCore.QString('def'))

u'def'

>>> print unicode(QtCore.QString('def'))

def

對于中 文,unicode()必須要指定編碼後有效。(這樣也隻針對直接的QString有效?對于Qt GUI程式設計中,從QWidget取得的QString無效?)

>>> from PyQt4 import QtGui, QtCore

>>> unicode(QtCore.QString('中文'))

u'xd6xd0xcexc4'

>>> print unicode(QtCore.QString('中文'))

Traceback (most recent call last):

File "<stdin>", line 1, in <module>

UnicodeEncodeError: 'gbk' codec can't encode character u'xd6' in position 0: il

legal multibyte sequence

指定原始編碼後:

>>> unicode(QtCore.QString('中文'),'gbk','ignore')

u'u4e2du6587'

>>> print unicode(QtCore.QString('中文'),'gbk','ignore')

中文

>>>

GUI程式設計中:

但這種方法在GUI程式設計中似乎無效?

比如建立一個QLineEdit對象myLineEdit,寫入漢字,則:

myText = unicode(self.myLineEdit.text(),'gb2312','ignore')

myText = unicode(QtCore.QString(self.myLineEdit.text()),'gb2312','ignore')

print myText都是亂碼.

嘗試将 unicode()的參數改為QByteArray,但QString沒有toGbk()或toGb2312()函數,隻有toUtf8()和 toAsciii()函數,利用下試試:

myText = unicode(self.myLineEdit.text().toUtf8(),'utf8', 'ignore')

myText = unicode(self.myLineEdit.text().toAscii(),'ascii', 'ignore')

因為不是gbk編碼,是以列印都還是亂碼。

不過python中一 般從檔案、終端、網絡資料流或者其它外部輸入中讀取的都是Python string object類型,而且向檔案、終端、網絡也隻能輸出Python string object類型。是以這個問題可以跳過,通過下面講的内容,發現可以在此基礎上轉為Python string object使用。

2)QString向 Python string object的轉換。

A. 第一種方法:

可以直接借助上一步得到的Python Unicode object和encode()函數獲得Python string object。

>>> unicode(QtCore.QString('dfd')).encode('gb2312')

'dfd'

>>> unicode(QtCore.QString('dfd')).encode('ascii')

'dfd'

>>>

>>> unicode(QtCore.QString('中文'),'gbk','ignore').encode('gbk')

'xd6xd0xcexc4'

>>> print unicode(QtCore.QString('中文'),'gbk','ignore').encode('gbk')

中文

>>>

B. 第二種方法:

也可利用str():

>>> str(QtCore.QString('def'))

'def'

>>> print str(QtCore.QString('def'))

def

>>>

但是對于中文,直接調 用str()是無效的!

>>> str(QtCore.QString('中文'))

Traceback (most recent call last):

File "<stdin>", line 1, in <module>

UnicodeEncodeError: 'ascii' codec can't encode characters in position 0-3: ordin

al not in range(128)

對于str()函數預設以ascii編碼轉換,而str()函數又隻能接受一個參數,改不了别的編碼,是以對漢字自然不行。

先用unicode()指定gb2312解碼再利用str()呢?:

>>> str(unicode(QtCore.QString('中文'), 'gb2312', 'ignore'))

Traceback (most recent call last):

File "<stdin>", line 1, in <module>

UnicodeEncodeError: 'ascii' codec can't encode characters in position 0-1: ordin

al not in range(128)

還是----str()函數預設以ascii編碼轉換!

C. 對于中文考慮第一種方法:

>>> unicode(QtCore.QString('中文'),'gbk','ignore').encode('gbk')

'xd6xd0xcexc4'

>>> unicode(QtCore.QString('中文'),'gbk','ignore').encode('gb2312')

'xd6xd0xcexc4'

>>> print unicode(QtCore.QString('中文'),'gbk','ignore').encode('gb2312')

中文

>>> print unicode(QtCore.QString('中文'),'gbk','ignore')

中文

>>>

GUI程式設計中:

但是對于前面myLineEdit的情況怎麼處理呢?

myText = unicode(self.myLineEdit.text(),'gb2312','ignore')是亂碼,encode('gb2312')之後 呢?

myText = unicode(self.myLineEdit.text(),'gb2312','ignore').encode('gb2312')

列印依然是亂碼!?

後面嘗試将unicode()的參數改為QByteArray、利用QString的toUtf8()得到的雖然不是gbk編碼,但是進一步 encode('gb2312')又如何呢:

myText = unicode(self.myLineEdit.text().toUtf8(),'utf8', 'ignore').encode('gb2312')

發現print myText顯示正常!!!:

中文

且python方式打開檔案後查找該字元串也正常,證明myText是轉換成功的Python string object!!!

注意:1)借助 toAscii()函數(除了toUtf8隻有這個...)不行?!

myText = unicode(self.myLineEdit.text().toAscii(),'ascii', 'ignore').encode('gb2312')

列印是亂碼。

難道PyQt的Ascii和Python的ascii不一樣?

2)這種借助utf8碼的方式對于直接的QString反而不行!?

>>> unicode(QtCore.QString('中文').toUtf8(),'utf8','ignore').encode('gb2312')

Traceback (most recent call last):

File "<stdin>", line 1, in <module>

UnicodeEncodeError: 'gb2312' codec can't encode character u'xd6' in position 0:

illegal multibyte sequence

>>> unicode(QtCore.QString('中文 ').toAscii(),'ascii','ignore').encode('gb2312')

''

>>> print unicode(QtCore.QString('中文').toAscii(),'ascii','ignore').encode('gb2

312')

>>>

D. 對于中文考慮第二種方法:

利用QString的toAscii()函數後再使用str()函數:

>>> str(QtCore.QString('中文').toAscii())

'xd6xd0xcexc4'

>>> print str(QtCore.QString('中文').toAscii())

中文

>>>

str(QtCore.QString('中文').toAscii())得到的是ascii編碼?嘗試将其轉為unicode?

>>> unicode(str(QtCore.QString('中文').toAscii())).encode('gbk')

Traceback (most recent call last):

File "<stdin>", line 1, in <module>

UnicodeDecodeError: 'ascii' codec can't decode byte 0xd6 in position 0: ordinal

not in range(128)

>>> unicode(str(QtCore.QString('中文').toAscii()),'ascii').encode('gbk')

Traceback (most recent call last):

File "<stdin>", line 1, in <module>

UnicodeDecodeError: 'ascii' codec can't decode byte 0xd6 in position 0: ordinal

not in range(128)

>>> unicode(str(QtCore.QString('中文 ').toAscii()),'ascii','ignore').encode('gbk'

)

''

>>>

>>> unicode(str(QtCore.QString('中文').toAscii()))

Traceback (most recent call last):

File "<stdin>", line 1, in <module>

UnicodeDecodeError: 'ascii' codec can't decode byte 0xd6 in position 0: ordinal

not in range(128)

難道PyQt的Ascii和Python的ascii不一樣?

GUI程式設計中:

myText = str(self.myLineEdit.text().toAscii())

列印發現還是亂碼!?

myText = unicode(str(self.myLineEdit.text().toAscii())).encode('gb2312')

列印發現還是亂碼!?

6. 總結:

1)Python string object是原始編碼是有區分的,通過 decode('原始編碼') 解碼得到utf16類型即Python Unicode object。Python Unicode object原始編碼固定是utf16,通過 encode('目的編碼') 編碼來得到Python string object。

2)對于英 文,PyQt函數需要QString參數的地方都可以直接用Python string object或者Python Unicode object。對于中文,利用unicode()函數顯示指定gb2312編碼進行中文編碼轉換,轉換後的Python Unicode object可以直接作為QString參數代入。

unicode('中 文', 'gb2312', 'ignore')

3)對于英文,可以使 用unicode()直接将QString轉換為Python Unicode object,并進一步encode()得到Python string object,也可以使用str()函數直接将QString轉換為Python string object。對于中文,利用unicode()指定原始編碼gbk來解決QString轉換為Python Unicode object問題,但對于GUI使用仍有缺陷,不過無礙;進一步利用encode('gb2

312')得到Python string object,或者結合QString的toUtf8()再利用str()函數;但對于GUI程式設計str()方法還是不行,隻可結合QString的 toUtf8()進行unicode()轉換後再利用encode('gb2

312')。

str(QtCore.QString(' 中文').toAscii())

unicode(QtCore.QString('中文'),'gbk','ignore').encode('gb2312')

myText = unicode(self.myLineEdit.text().toUtf8(),'utf8', 'ignore').encode('gb2312')

7. 中文?為什麼不用類似C++中Qt的方法解決上面中文的使用?

C++中Qt一般是利用tr()方法翻譯(便于國際化),或者簡單設定:

    QTextCodec::setCodecForTr(QTextCodec::codecForName("GB2312"));

    QTextCodec::setCodecForCStrings(QTextCodec::codecForName("GB2312"));

    QTextCodec::setCodecForLocale(QTextCodec::codecForName("GB2312"));

    1)前者PyQt4中對應是QCoreApplication.translate(),比如pyuic4自動生成的.py檔案中可以看到:

    def retranslateUi(self, mainWindow):

        mainWindow.setWindowTitle(QtGui.QApplication.translate("mainWindow", "名稱", None, QtGui.QApplication.UnicodeUTF8))

     QtGui.QApplication.UnicodeUTF8繼承自QCoreApplication的

     enum Encoding { CodecForTr, UnicodeUTF8, DefaultCodec }

     但這需保證寫入的漢字是UnicodeUTF8編碼,比如前面myLineEdit讀入的ini檔案中漢字就需用utf8表示?CodecForTr是使 用QTextCodec.codecForTr() (Latin-1 if none has been set).但後面可看到PyQt4中無code包?

        PyQt4手冊說明如下:

    Unfortunately, because of the way Qt implements tr() (and trUtf8()) it is not possible for PyQt to exactly reproduce its behaviour. The PyQt implementation of tr() (and trUtf8()) uses the class name of the instance as the context. The key difference, and the source of potential problems, is that the context is determined dynamically in PyQt, but is hardcoded in Qt. In other words, the context of a translation may change depending on an instance's class hierarchy.

The PyQt behaviour is unsatisfactory and may be changed in the future. It is recommended that QCoreApplication.translate() be used in preference to tr() (and trUtf8()). This is guaranteed to work with current and future versions of PyQt and makes it much easier to share message files between Python and C++ code. Below is the alternative implementation of A that uses QCoreApplication.translate():

class A(QtCore.QObject):

    def hello(self):

        return QtCore.QCoreApplication.translate("A", "Hello")

    2) 但後者方法在PyQt中未能成功:

    QtCore.QTextCodec.setCodecForTr(QtCore.QTextCodec.codecForName("gb2312"))

    QtCore.QTextCodec.setCodecForCStrings(QtCore.QTextCodec.codecForName("gb2312"))

    QtCore.QTextCodec.setCodecForLocale(QtCore.QTextCodec.codecForName("gb2312"))

    後證明PyQt4中無code包?ascii也沒有?...

    if not QtCore.QTextCodec.codecForName("gb2312"):

        print 'no code'

轉載于:https://www.cnblogs.com/babykick/archive/2011/05/16/2048155.html