私は、Googleドキュメントからデータを取り出し、それを処理し、それをファイルに書き出しています(最終的にはWordpressのページに貼り付けます)。
ASCII以外のシンボルがいくつかあります。これらをHTMLソースで使用できるシンボルに安全に変換する方法を教えてください。
現在私は、途中ですべてをUnicodeに変換し、それをすべてPythonストリングに結合してから、次のようにしています。
import codecs
f = codecs.open('out.txt', mode="w", encoding="iso-8859-1")
f.write(all_html.encode("iso-8859-1", "replace"))
最後の行にエンコードエラーがあります。
UnicodeDecodeError: 'ascii'コーデックは位置12286のバイト0xa0をデコードできません:序数が範囲外(128)
部分解:
このPythonはエラーなしで動作します。
row = [unicode(x.strip()) if x is not None else u'' for x in row]
all_html = row[0] + "<br/>" + row[1]
f = open('out.txt', 'w')
f.write(all_html.encode("utf-8"))
しかし、実際のテキストファイルを開くと、たくさんのシンボルが表示されます。
Qur’an
たぶん私はテキストファイル以外の何かに書く必要がありますか?
Unicodeオブジェクトを最初に入手したときにそれらをUnicodeオブジェクトにデコードし、必要に応じてエンコードすることによって、可能な限りUnicodeオブジェクトに排他的に対処します。
文字列が実際にUnicodeオブジェクトの場合は、ファイルに書き込む前にUnicodeエンコードの文字列オブジェクトに変換する必要があります。
foo = u'Δ, Й, ק, م, ๗, あ, 叶, 葉, and 말.'
f = open('test', 'w')
f.write(foo.encode('utf8'))
f.close()
そのファイルをもう一度読むと、UnicodeオブジェクトにデコードできるUnicodeエンコードの文字列が得られます。
f = file('test', 'r')
print f.read().decode('utf8')
Python 2.6以降では、Python 3では io.open()
がデフォルトになります( 組み込みopen()
)。
import io
with io.open(filename, 'w', encoding=character_encoding) as file:
file.write(unicode_text)
テキストを少しずつ書く必要がある場合(unicode_text.encode(character_encoding)
を複数回呼び出す必要がない場合)は、もっと便利かもしれません。 codecs
モジュールとは異なり、io
モジュールは適切なユニバーサル改行をサポートしています。
Unicode文字列処理はPython 3で標準化されています。
あなただけのutf-8でファイルを開く必要があります
out1 = "(嘉南大圳 ㄐㄧㄚ ㄋㄢˊ ㄉㄚˋ ㄗㄨㄣˋ )"
fobj = open("t1.txt", "w", encoding="utf-8")
fobj.write(out1)
fobj.close()
codecs.open
によって開かれたファイルは、unicode
データを受け取り、それをiso-8859-1
にエンコードしてファイルに書き込むファイルです。しかし、あなたが書いたのはunicode
ではありません。あなたはunicode
を取り、それをiso-8859-1
yourselfにエンコードします。それがunicode.encode
メソッドの動作で、Unicode文字列をエンコードした結果はバイト文字列(str
型)になります。
通常のopen()
を使って自分でUnicodeをエンコードするか、(通常はcodecs.open()
を使ってnot自分でデータをエンコードする)べきです。
あなたのビューア/エディタ/端末(しかしあなたがあなたのutf-8でエンコードされたファイルと対話している)がファイルを読むことができることを確認してください。これは、 Windows (たとえばメモ帳)で頻繁に問題になります。
テキストファイルへのUnicodeテキストの書き込み
Python 2では、open
モジュールのio
を使用します(これはPython 3の組み込みのopen
と同じです)。
import io
ベストプラクティスは、一般に、ファイルへの書き込みにUTF-8
を使用することです(utf-8ではバイト順について心配する必要すらありません)。
encoding = 'utf-8'
utf-8は最も近代的で普遍的に使用可能なエンコーディングです - それはすべてのWebブラウザ、ほとんどのテキストエディタ(問題があればあなたの設定を参照してください)そしてほとんどの端末/シェルで動作します。
Windowsでは、メモ帳(または別の限られたビューア)で出力を表示することに限定されている場合はutf-16le
を試すことができます。
encoding = 'utf-16le' # sorry, Windows users... :(
そして、コンテキストマネージャでそれを開き、あなたのUnicode文字を書き出してください。
with io.open(filename, 'w', encoding=encoding) as f:
f.write(unicode_object)
以下は、可能なすべての文字をデジタル表現(整数)から符号化された印刷可能な出力に、最大3ビット幅(4が最大ですが、少し遠くなるまで)にマップする例です。可能です(これをuni.py
というファイルに入れてください):
from __future__ import print_function
import io
from unicodedata import name, category
from curses.ascii import controlnames
from collections import Counter
try: # use these if Python 2
unicode_chr, range = unichr, xrange
except NameError: # Python 3
unicode_chr = chr
exclude_categories = set(('Co', 'Cn'))
counts = Counter()
control_names = dict(enumerate(controlnames))
with io.open('unidata', 'w', encoding='utf-8') as f:
for x in range((2**8)**3):
try:
char = unicode_chr(x)
except ValueError:
continue # can't map to unicode, try next x
cat = category(char)
counts.update((cat,))
if cat in exclude_categories:
continue # get rid of noise & greatly shorten result file
try:
uname = name(char)
except ValueError: # probably control character, don't use actual
uname = control_names.get(x, '')
f.write(u'{0:>6x} {1} {2}\n'.format(x, cat, uname))
else:
f.write(u'{0:>6x} {1} {2} {3}\n'.format(x, cat, char, uname))
# may as well describe the types we logged.
for cat, count in counts.items():
print('{0} chars of category, {1}'.format(count, cat))
これは約1分程度で実行され、データファイルを表示できます。ファイルビューアにUnicodeが表示される場合は、それが表示されます。カテゴリに関する情報は こちら で見つけることができます。カウントに基づいて、シンボルが関連付けられていないCnカテゴリとCoカテゴリを除外することで、おそらく結果を改善できます。
$ python uni.py
16進数のマッピング、 カテゴリ 、シンボル(名前を取得できない場合を除いて、制御文字)、およびシンボルの名前が表示されます。例えば.
私はUnixやCygwinでless
を使うことをお勧めします(ファイル全体をあなたの出力に表示したり/出力しないでください):
$ less unidata
例えばPython 2(unicode 5.2)を使ってサンプリングした次の行のように表示されます。
0 Cc NUL
20 Zs SPACE
21 Po ! EXCLAMATION MARK
b6 So ¶ PILCROW SIGN
d0 Lu Ð LATIN CAPITAL LETTER ETH
e59 Nd ๙ THAI DIGIT NINE
2887 So ⢇ BRAILLE PATTERN DOTS-1238
bc13 Lo 밓 HANGUL SYLLABLE MIH
ffeb Sm → HALFWIDTH RIGHTWARDS ARROW
Anacondaからの私のPython 3.5はユニコード8.0を持っています、私はほとんどの3がすると思います。
ファイルにUnicode文字を印刷する方法
これをファイルに保存します:foo.py:
#!/usr/bin/python -tt
# -*- coding: utf-8 -*-
import codecs
import sys
UTF8Writer = codecs.getwriter('utf8')
sys.stdout = UTF8Writer(sys.stdout)
print(u'e with obfuscation: é')
実行して、出力をファイルにパイプ処理します。
python foo.py > tmp.txt
Tmp.txtを開いて中を見ると、これがわかります。
el@apollo:~$ cat tmp.txt
e with obfuscation: é
つまり、難読化マークを付けたUnicode eをファイルに保存しました。
あなたが非Unicode文字列をエンコードしようとすると、そのエラーが発生します:それはプレーンASCIIであると仮定して、それをデコードしようとします。 2つの可能性があります。
f.write(all_html)
をお試しください。.encode(...)
を実行すると、まずそれをデコードしようとします。Python3に書く場合
>>> a = u'bats\u00E0'
>>> print a
batsà
>>> f = open("/tmp/test", "w")
>>> f.write(a)
>>> f.close()
>>> data = open("/tmp/test").read()
>>> data
'batsà'
Python2に書く場合:
>>> a = u'bats\u00E0'
>>> f = open("/tmp/test", "w")
>>> f.write(a)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
UnicodeEncodeError: 'ascii' codec can't encode character u'\xe0' in position 4: ordinal not in range(128)
このエラーを回避するには、コーデック "utf-8"を使ってバイトにエンコードする必要があります。
>>> f.write(a.encode("utf-8"))
>>> f.close()
そして、コーデック "utf-8"を使って読みながらデータをデコードします。
>>> data = open("/tmp/test").read()
>>> data.decode("utf-8")
u'bats\xe0'
また、この文字列に対してprintを実行しようとすると、このような "utf-8"コーデックを使って自動的にデコードされます。
>>> print a
batsà