この問題は通常、py2からpy3に切り替えるときに発生します。py2 plaintext
では文字列とバイト配列型の両方です。py3 plaintext
では文字列のみであり、バイナリモードで開いた場合、メソッドはoutfile.write()
実際にはバイト配列をとるoutfile
ため、例外が発生します。入力を変更しplaintext.encode('utf-8')
て問題を修正します。これがあなたを悩ませているなら、読んでください。
py2では、file.writeの宣言により、文字列で渡されたように見えました:file.write(str)
。実際にはバイト配列を渡していたので、次のような宣言を読んでいるはずですfile.write(bytes)
。あなたはこのようにそれを読めば、問題は単純で、file.write(bytes)
必要とするバイトの取得にタイプとPY3でのバイトのうちSTRあなたがそれを変換します。
py3>> outfile.write(plaintext.encode('utf-8'))
py2 docs宣言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はこの素晴らしいシステムを壊したのですか?まあ、py2では基本的な文字列関数が他の地域では機能しなかったからです。非ASCII文字を含む単語の長さを測定しますか?
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のクラスは、メソッド紐状、別個たバイトのクラスは、バイト配列のメソッドがあります。
py3>> len('¡ok') #string
3
py3>> len('¡ok'.encode('utf-8')) #bytes
4
うまくいけば、これを理解することで問題の謎を解きやすくなり、移行の苦痛がやや緩和されます。