Python ファイルとオペレーティング システムの基本

記事とコードは [Github ウェアハウス: https://github.com/timerring/dive-into-AI] にアーカイブされているか、[AIShareLab] のpython データ分析への返信も利用できます。

ファイルとオペレーティング システム

コード例では、ほとんどの場合、ディスク上のデータ ファイルを Python データ構造に読み込むpandas.read_csvなど。しかし、Python のファイル処理に関するいくつかの基本を知る必要があります。

読み書き用にファイルを開くには、組み込みの open 関数を相対または絶対ファイル パスで使用します。

In [207]: path = 'examples/segismundo.txt'

In [208]: f = open(path)

デフォルトでは、ファイルは読み取り専用モード ('r') で開かれます。次に、行を反復するなど、このファイルハンドル f をリストのように処理できます。

for line in f:
    pass

行は完全な行末 (EOL) でファイルからフェッチされるため、次のようなコードがよく見られます (EOL なしで一連の行を取得します)。

In [209]: lines = [x.rstrip() for x in open(path)]

In [210]: lines
Out[210]: 
['Sueña el rico en su riqueza,',
 'que más cuidados le ofrece;',
 '',
 'sueña el pobre que padece',
 'su miseria y su pobreza;',
 '',
 'sueña el que a medrar empieza,',
 'sueña el que afana y pretende,',
 'sueña el que agravia y ofende,',
 '',
 'y en el mundo, en conclusión,',
 'todos sueñan lo que son,',
 'aunque ninguno lo entiende.',
 '']

open を使用してファイル オブジェクトを作成する場合は、必ず close で閉じてください。ファイルを閉じると、オペレーティング システムのリソースが返される場合があります。

In [211]: f.close()

with ステートメントを使用すると、開いているファイルをより簡単にクリーンアップできます

In [212]: with open(path) as f:
   .....:     lines = [x.rstrip() for x in f]

これにより、コード ブロックを終了するときにファイルが自動的に閉じられます。

f =open(path,'w') と入力すると、examples/segismundo.txt に新しいファイルが作成され、その場所にある以前のデータが上書きされます書き込み可能なファイルを作成する xfile モードもありますが、ファイル パスが存在する場合は作成に失敗します。表 3-3 に、すべての読み取り/書き込みモードを示します。

読み取り可能なファイルの場合、いくつかの一般的な方法は read、seek、および tell です。read はファイルから文字を返します。文字の内容は、ファイルのエンコーディング (UTF-8 など) によって決まります。バイナリ モードで開いた場合は、元のバイトになります。

In [213]: f = open(path)

In [214]: f.read(10)
Out[214]: 'Sueña el r'

In [215]: f2 = open(path, 'rb')  # Binary mode

In [216]: f2.read(10)
Out[216]: b'Sue\xc3\xb1a el '

読み取りモードは、読み取ったバイト数だけファイルハンドルの位置を進めます。tell は現在の場所を与えることができます:

In [217]: f.tell()
Out[217]: 11

In [218]: f2.tell()
Out[218]: 10

ファイルから 10 文字を読み取りましたが、位置は 11 です。これは、デフォルトのエンコーディングでこれらの 10 文字をデコードするのに非常に多くのバイトが必要だったためです。デフォルトのエンコーディングは sys モジュールで確認できます:

In [219]: import sys

In [220]: sys.getdefaultencoding()
Out[220]: 'utf-8'

seek は、ファイルの位置をファイル内の指定されたバイトに変更します。

In [221]: f.seek(3)
Out[221]: 3

In [222]: f.read(1)
Out[222]: 'ñ'

最後に、ファイルを閉じます。

In [223]: f.close()

In [224]: f2.close()

ファイルに書き込むには、ファイルの write または writelines メソッドを使用できます。たとえば、空白行のないバージョンの prof_mod.py を作成できます。

In [225]: with open('tmp.txt', 'w') as handle:
   .....:     handle.writelines(x for x in open(path) if len(x) > 1)

In [226]: with open('tmp.txt') as f:
   .....:     lines = f.readlines()

In [227]: lines
Out[227]: 
['Sueña el rico en su riqueza,\n',
 'que más cuidados le ofrece;\n',
 'sueña el pobre que padece\n',
 'su miseria y su pobreza;\n',
 'sueña el que a medrar empieza,\n',
 'sueña el que afana y pretende,\n',
 'sueña el que agravia y ofende,\n',
 'y en el mundo, en conclusión,\n',
 'todos sueñan lo que son,\n',
 'aunque ninguno lo entiende.\n']

表 3-4 に、最も一般的に使用されるファイル メソッドの一部を示します。

ファイルのバイト数と Unicode

Python ファイルのデフォルトの操作は「テキスト モード」です。つまり、Python 文字列 (つまり Unicode) を処理する必要があります。「バイナリモード」の逆で、ファイルモードに b を追加します。前のセクションのファイルを見てみましょう (非 ASCII 文字を含む UTF-8 エンコーディング):

In [230]: with open(path) as f:
   .....:     chars = f.read(10)

In [231]: chars
Out[231]: 'Sueña el r'

UTF-8 は可変長の Unicode エンコーディングであるため、ファイルから特定の数の文字を要求すると、Python はファイルから十分な (おそらく 10 バイトから 40 バイト程度の) バイトを読み取ってデコードします。ファイルが「rb」モードで開かれている場合、要求された正確なバイト数が読み取られます。

In [232]: with open(path, 'rb') as f:
   .....:     data = f.read(10)

In [233]: data
Out[233]: b'Sue\xc3\xb1a el '

テキストのエンコーディングに応じて、バイトを str オブジェクトにデコードできますが、エンコードされた各 Unicode 文字が完全に形成されている場合に限ります。

In [234]: data.decode('utf8')
Out[234]: 'Sueña el '

In [235]: data[:4].decode('utf8')
---------------------------------------------------------------------------
UnicodeDecodeError                        Traceback (most recent call last)
<ipython-input-235-300e0af10bb7> in <module>()
----> 1 data[:4].decode('utf8')
UnicodeDecodeError: 'utf-8' codec can't decode byte 0xc3 in position 3: unexpecte
d end of data

テキスト モードは、open のエンコーディング オプションを組み合わせて、Unicode を別のエンコーディングに変換するためのより便利な方法を提供します。

In [236]: sink_path = 'sink.txt'

In [237]: with open(path) as source:
   .....:     with open(sink_path, 'xt', encoding='iso-8859-1') as sink:
   .....:         sink.write(source.read())

In [238]: with open(sink_path, encoding='iso-8859-1') as f:
   .....:     print(f.read(10))
Sueña el r

バイナリ モードでシークを使用しないでください。ファイルの位置が Unicode 文字を定義するバイトの中間にある場合、後で読み取るとエラーが発生します。

In [240]: f = open(path)

In [241]: f.read(5)
Out[241]: 'Sueña'

In [242]: f.seek(4)
Out[242]: 4

In [243]: f.read(1)
---------------------------------------------------------------------------
UnicodeDecodeError                        Traceback (most recent call last)
<ipython-input-243-7841103e33f5> in <module>()
----> 1 f.read(1)
/miniconda/envs/book-env/lib/python3.6/codecs.py in decode(self, input, final)
    319         # decode input (taking the buffer into account)
    320         data = self.buffer + input
--> 321         (result, consumed) = self._buffer_decode(data, self.errors, final
)
    322         # keep undecoded input until the next call
    323         self.buffer = data[consumed:]
UnicodeDecodeError: 'utf-8' codec can't decode byte 0xb1 in position 0: invalid s
tart byte

In [244]: f.close()

非 ASCII 文字テキストでデータ分析を頻繁に実行する必要がある場合は、Python の Unicode 関数に精通していることが非常に重要です。詳細については、Python の公式ドキュメントを参照してください。

Guess you like

Origin blog.csdn.net/m0_52316372/article/details/130490399