これは素晴らしい質問です。
open()
またはでファイルを開くかどうかによって違いが生じますcodecs.open()
。前者はバイト文字列の観点から動作します。後者は、Unicode 文字列に関して動作します。Python では、これらの動作は異なります。
これと同じ質問がPython Issue 7643, What is a Unicode line break character?として出てきました。. 議論とUnicode Character Databaseへの引用は興味深いものです。問題 7643 では、違いを示すために次の簡潔なコード スニペットも提供されています。
for s in '\x0a\x0d\x1c\x1d\x1e':
print u'a{}b'.format(s).splitlines(1), 'a{}b'.format(s).splitlines(1)
しかし、それはこれに要約されます。
バイト文字列内のバイトが改行 (または空白) であるかどうかを判断するために、Python はASCII 制御文字の規則を使用します。その尺度では、バイト 10 と 13 は改行文字です (そして、Python はバイト 13 とそれに続く 10 を単一の改行として扱います)。
しかし、Unicode 文字列の文字が改行であるかどうかを判断するために、Python はUAX #44に記載されているUnicode Character Databaseの文字分類と、UAX #14 Line Breaking Algorithmの section 5 Line Breaking Propertiesの文字分類に従います。Issue 7643 によると、これらのドキュメントは、Python の目的で文字を改行として識別する 3 つの文字プロパティを識別します。
- 大分類Zl「ラインセパレーター」
- 一般カテゴリZp「段落区切り」
- 双方向クラス B「段落区切り」
文字 28 (0x001C)、29 (0x001D)、および 30 (0x001E) には、これらの文字プロパティがあります。文字 31 (0x001F) にはありません。なんで?これは Unicode 技術委員会への質問です。しかし、ASCII では、これらの文字は「ファイル区切り」、「グループ区切り」、「レコード区切り」、および「単位区切り」として知られていました。比較としてタブ付きのテキスト データ ファイルを使用すると、最初の 3 つは少なくとも改行と同じくらいの分離を意味し、4 番目はおそらくタブに類似しています。
これら 3 つの Unicode 文字を Python Unicode 文字列の改行として実際に定義しているコードをObjects/unicodeobject.c
. array を探しascii_linebreak[]
ます。この配列はunicode.splitlines()
の実装の基礎となります。strの基礎となるコードが異なります.splitlines()
。私は信じていますが、Pythonソースコードでそれを追跡していません.でenumerate()
開かれたファイルはunicodecodecs.open()
の観点から実装されています..splitlines()
「どうすればそうならないようにできますか?」と尋ねます。splitlines()
異なる動作をさせる方法がわかりません。ただし、ファイルをバイトストリームとして開き、str.splitlines()
動作を使用して行をバイトとして読み取り、各行を UTF-8 としてデコードして Unicode 文字列として使用することができます。
with open('unicodetest.txt', 'r') as f:
for i,l in enumerate(f):
print i, l.decode('UTF-8')
# prints "0 abcde" with special characters in between.
3.x ではなく Python 2.x を使用していると思います。私の答えは Python 2.7 に基づいています。