plaintext = input("Please enter the text you want to compress")
filename = input("Please enter the desired filename")
with gzip.open(filename + ".gz", "wb") as outfile:
outfile.write(plaintext)
上記のPythonコードは私に次のようなエラーを出しています:
Traceback (most recent call last):
File "C:/Users/Ankur Gupta/Desktop/Python_works/gzip_work1.py", line 33, in <module>
compress_string()
File "C:/Users/Ankur Gupta/Desktop/Python_works/gzip_work1.py", line 15, in compress_string
outfile.write(plaintext)
File "C:\Python32\lib\gzip.py", line 312, in write
self.crc = zlib.crc32(data, self.crc) & 0xffffffff
TypeError: 'str' does not support the buffer interface
Python3xを使う場合、string
はPython 2.xと同じ型ではないので、それをバイトにキャスト(エンコード)する必要があります。
plaintext = input("Please enter the text you want to compress")
filename = input("Please enter the desired filename")
with gzip.open(filename + ".gz", "wb") as outfile:
outfile.write(bytes(plaintext, 'UTF-8'))
また、string
やfile
のような変数名はモジュールや関数の名前ですが、使わないでください。
@Tomを編集
はい、ASCII以外のテキストも圧縮/解凍されます。私はUTF-8エンコーディングのポーランド文字を使います。
plaintext = 'Polish text: ąćęłńóśźżĄĆĘŁŃÓŚŹŻ'
filename = 'foo.gz'
with gzip.open(filename, 'wb') as outfile:
outfile.write(bytes(plaintext, 'UTF-8'))
with gzip.open(filename, 'r') as infile:
outfile_content = infile.read().decode('UTF-8')
print(outfile_content)
この問題に対するより簡単な解決策があります。
t
をモードに追加するだけで、wt
になります。これにより、Pythonはファイルをバイナリではなくテキストファイルとして開きます。それからすべてがうまくいくでしょう。
完全なプログラムはこれになります:
plaintext = input("Please enter the text you want to compress")
filename = input("Please enter the desired filename")
with gzip.open(filename + ".gz", "wt") as outfile:
outfile.write(plaintext)
Python 3 'string'を、何らかのエンコーディングへの明示的な変換なしでバイトにシリアル化することはできません。
outfile.write(plaintext.encode('utf-8'))
おそらくあなたが望むものです。また、これはpython 2.xと3.xの両方で機能します。
Python 3.xでは、テキストを生のバイトに変換することができます。
bytes("my data", "encoding")
例えば:
bytes("attack at dawn", "utf-8")
返されたオブジェクトはoutfile.write
で動作します。
この問題は通常、py2からpy3に切り替えると発生します。 py2ではplaintext
は文字列とバイト配列型の両方です。 py3ではplaintext
は文字列のみであり、outfile
がバイナリモードで開かれている場合、メソッドoutfile.write()
は実際にはバイト配列を取ります。発生します。問題を解決するために入力をplaintext.encode('utf-8')
に変更してください。これがあなたを悩ませているなら読んでください。
Py2では、 file.writeの宣言 によって、file.write(str)
という文字列を渡したように見えます。実際にはあなたはバイト配列を渡していました、あなたはこのような宣言を読んでいたはずです:file.write(bytes)
。このように読めば問題は単純です、file.write(bytes)
は bytes typeを必要とし、py3では bytes をから取り出すために必要です。 //] str あなたはそれを変換する:
py3>> outfile.write(plaintext.encode('utf-8'))
なぜpy2ドキュメントはfile.write
が文字列を取ると宣言したのですか? py2では、宣言の区別は重要ではありませんでした。
py2>> str==bytes #str and bytes aliased a single hybrid class in py2
True
Py2の str-bytes クラスには、ある意味では文字列クラス、それ以外のバイト配列クラスのように動作させるメソッド/コンストラクタがあります。 file.write
に便利ではありませんか?
py2>> plaintext='my string literal'
py2>> type(plaintext)
str #is it a string or is it a byte array? it's both!
py2>> outfile.write(plaintext) #can use plaintext as a byte array
なぜpy3はこのNiceシステムを壊したのですか?それは、py2では基本的な文字列関数が他の国々ではうまくいかなかったからです。 ASCII以外の文字でWordの長さを測りますか?
py2>> len('¡no') #length of string=3, length of UTF-8 byte array=4, since with variable len encoding the non-ASCII chars = 2-6 bytes
4 #always gives bytes.len not str.len
Py2で文字列の len を要求していると思っていた間、あなたはエンコーディングからバイト配列の長さを取得していました。そのあいまいさは二重義務クラスの根本的な問題です。どのメソッド呼び出しのどのバージョンを実装していますか?
それで良いニュースはpy3がこの問題を解決することです。それは str と bytes クラスを解く。 str クラスは文字列のようなメソッドを持ち、別の bytes クラスはバイト配列メソッドを持ちます:
py3>> len('¡ok') #string
3
py3>> len('¡ok'.encode('utf-8')) #bytes
4
うまくいけば、これを理解しておくと問題がわかりにくくなり、移行の痛みがやや軽減されます。
Django.test.TestCase
単体テストのDjango
については、私のPython2の構文を変更しました。
def test_view(self):
response = self.client.get(reverse('myview'))
self.assertIn(str(self.obj.id), response.content)
...
Python3.decode('utf8')
構文を使うには、
def test_view(self):
response = self.client.get(reverse('myview'))
self.assertIn(str(self.obj.id), response.content.decode('utf8'))
...
>>> s = bytes("s","utf-8")
>>> print(s)
b's'
>>> s = s.decode("utf-8")
>>> print(s)
s
迷惑な「b」文字を削除する場合に役立つ場合もあります。誰かが良いアイデアを得た場合は、私に提案するか、ここでいつでも編集してください。私は単なる初心者です