Python/ファイルの書き込みと読み込み

ファイルへの書込み

編集

ファイルを書くにも読むにも、まず、そのファイルを開く必要があります。 ファイルを開くには、組込み関数 open() を使います。 もしopen()をするときにその名前のファイルがなければ、ファイルを作成されます。

ファイルへの書込みの例
with open("create.txt", "w") as f:
    print("hello", file=f)

open()の2番目の引数にある「"w"」は、「書込みモード」という意味です。 open()の戻り値は f に保持されます(f の型は _io.TextIOWrapper クラスです)。

open()の関数定義
open(file, mode='r', buffering=-1, encoding=None, errors=None, newline=None, closefd=True, opener=None)

ファイルに書込むには open() の戻り値 f を組込み関数 print() のキーワード引数 file に与えます。 組込み関数 print() は今まで何度も出てきましたが、キーワード引数 file には何も指定していなかったのでディフォルトの sys.stdout (標準出力)が仮定されていました。

オープンしたファイルは必ずクローズする必要があります。 この例では、with文を使っているのでブロックを抜けると自動的にクローズされます。

カレントディレクトリを見ると、「create.txt」という名のファイルが作成されており、開くと「hello」と書かれているはずです。

ファイルからの読込み

編集
ファイルへの一行読込みの例
with open("create.txt") as f:
    s = f.readline()
    print(s)

ここでは組込み関数 open() の第二引数『モード』を与えていませんので、ディフォルトのモード "r"(読込み)になります。 open() の戻り値 f をレシーバーにメソッド readline() を呼び出すと、ファイルから1行ずつ読み込むことができます。

上の例では、ファイルから一行だけ読み込み表示していましたが、全ての行を表示するには

ファイルの全内容を表示する例
with open("create.txt") as f:
    for s in f: 
        print(s, end='')

のように for文 を使います。 print() 関数のキーワード引数 end に を渡しているのは s には改行が含まれているため、 print() のディフォルトの動作「改行を追加する」をキャンセルするためです。

withとコンテキストマネージャ

編集

with文は、Pythonにおいてコンテキストマネージャを使用するための構文です。コンテキストマネージャは、特定のブロック内での処理を制御し、リソースの確保や解放、エラーハンドリングなどを行うための機能を提供します。

with文の一般的な使い方は次のようになります:

with コンテキストマネージャ as エイリアス:
    # ブロック内での処理
    # エイリアスを使ったリソースの操作

with文を使うと、ブロック内の処理の前後でコンテキストマネージャが自動的にリソースの確保や解放を行います。これにより、例外が発生した場合でもリソースを確実に解放することができます。

例えば、ファイルを扱う際にwith文を使ってファイルを開くと、ブロック内でファイルを操作した後、自動的にファイルを閉じることができます。これは、ファイルが閉じられないままになるリスクを減らすのに役立ちます。

with open('example.txt', 'r') as file:
    data = file.read()
    # ファイルを自動的に閉じるためのコード

また、独自のコンテキストマネージャを作成することもできます。これには、__enter____exit__という特殊メソッドを定義します。with文のブロックが開始すると__enter__メソッドが呼ばれ、ブロックが終了すると__exit__メソッドが呼ばれます。

class CustomContextManager:
    def __enter__(self):
        print("コンテキストを開始")
        return self
    
    def __exit__(self, exc_type, exc_value, traceback):
        print("コンテキストを終了")

# CustomContextManagerを使ったwith文
with CustomContextManager() as ccm:
    print("コンテキスト内での処理")

with文とコンテキストマネージャは、リソースの管理やクリーンアップを効果的に行うための便利な手段です。例外処理やリソースの解放などを自動化する際に活用されます。

withとtry-catchの使い分け

編集

with文とtry-except文(またはtry-catch文)は、それぞれ異なる目的で使用されますが、いくつかの共通点もあります。以下にそれぞれの違いと使い分けを示します。

  1. with文:
    • 目的: リソース管理やコンテキストの制御に使用されます。例えば、ファイルやネットワーク接続などのリソースを開いたり、操作した後に確実にクリーンアップするために使用します。
    • 動作: withブロック内でリソースを取得し、ブロックを抜けると自動的にリソースを解放します。
    • 例外処理: with文は例外処理を行うためのものではありませんが、コンテキストを抜ける際に__exit__メソッドが呼ばれ、リソースの解放が確実に行われます。
  2. try-except文:
    • 目的: 予期しないエラーや例外をキャッチして処理するために使用されます。プログラムの実行中に例外が発生した場合に、処理を中断せずに特定のエラーに対処したり、適切なメッセージをユーザーに表示したりするために使います。
    • 動作: tryブロック内のコードを実行し、例外が発生すると対応するexceptブロックが実行されます。
    • 例外処理: 例外が発生したときにその例外をキャッチし、適切な処理を行うことができます。

使い分けの例として、ファイルを開いて読み込む場合にはwith文を使ってファイルを開いて読み込み、そしてtry-except文を使ってファイルの読み込み中にエラーが発生した場合に処理を行うことができます。こうすることで、ファイルの自動クローズやエラーハンドリングを効果的に行うことができます。

まとめのコード

編集
まとめのコード
with open("/workspace/hello.txt", "w") as f:
    for x in 'city country world universe'.split():
        print(f"hello {x}", file=f)

with open("/workspace/hello.txt") as f:
    s = f.readline()
    print(s)

with open("/workspace/hello.txt") as f:
    for s in f: 
        print(s, end='')
        
with open("/workspace/hello.txt") as f:
    help(f)
実行結果
hello city

hello city
hello country
hello world
hello universe
Help on TextIOWrapper object:

class TextIOWrapper(_TextIOBase)
 |  TextIOWrapper(buffer, encoding=None, errors=None, newline=None, line_buffering=False, write_through=False)
 |  
 |  Character and line based layer over a BufferedIOBase object, buffer.
 |  
 |  encoding gives the name of the encoding that the stream will be
 |  decoded or encoded with. It defaults to locale.getpreferredencoding(False).
 |  
 |  errors determines the strictness of encoding and decoding (see
 |  help(codecs.Codec) or the documentation for codecs.register) and
 |  defaults to "strict".
 |  
 |  newline controls how line endings are handled. It can be None, '',
 |  '\n', '\r', and '\r\n'.  It works as follows:
 |  
 |  * On input, if newline is None, universal newlines mode is
 |    enabled. Lines in the input can end in '\n', '\r', or '\r\n', and
 |    these are translated into '\n' before being returned to the
 |    caller. If it is '', universal newline mode is enabled, but line
 |    endings are returned to the caller untranslated. If it has any of
 |    the other legal values, input lines are only terminated by the given
 |    string, and the line ending is returned to the caller untranslated.
 |  
 |  * On output, if newline is None, any '\n' characters written are
 |    translated to the system default line separator, os.linesep. If
 |    newline is '' or '\n', no translation takes place. If newline is any
 |    of the other legal values, any '\n' characters written are translated
 |    to the given string.
 |  
 |  If line_buffering is True, a call to flush is implied when a call to
 |  write contains a newline character.
 |  
 |  Method resolution order:
 |      TextIOWrapper
 |      _TextIOBase
 |      _IOBase
 |      builtins.object
 |  
 |  Methods defined here:
 |  
 |  __init__(self, /, *args, **kwargs)
 |      Initialize self.  See help(type(self)) for accurate signature.
 |  
 |  __next__(self, /)
 |      Implement next(self).
 |  
 |  __repr__(self, /)
 |      Return repr(self).
 |  
 |  close(self, /)
 |      Flush and close the IO object.
 |      
 |      This method has no effect if the file is already closed.
 |  
 |  detach(self, /)
 |      Separate the underlying buffer from the TextIOBase and return it.
 |      
 |      After the underlying buffer has been detached, the TextIO is in an
 |      unusable state.
 |  
 |  fileno(self, /)
 |      Returns underlying file descriptor if one exists.
 |      
 |      OSError is raised if the IO object does not use a file descriptor.
 |  
 |  flush(self, /)
 |      Flush write buffers, if applicable.
 |      
 |      This is not implemented for read-only and non-blocking streams.
 |  
 |  isatty(self, /)
 |      Return whether this is an 'interactive' stream.
 |      
 |      Return False if it can't be determined.
 |  
 |  read(self, size=-1, /)
 |      Read at most n characters from stream.
 |      
 |      Read from underlying buffer until we have n characters or we hit EOF.
 |      If n is negative or omitted, read until EOF.
 |  
 |  readable(self, /)
 |      Return whether object was opened for reading.
 |      
 |      If False, read() will raise OSError.
 |  
 |  readline(self, size=-1, /)
 |      Read until newline or EOF.
 |      
 |      Returns an empty string if EOF is hit immediately.
 |  
 |  reconfigure(self, /, *, encoding=None, errors=None, newline=None, line_buffering=None, write_through=None)
 |      Reconfigure the text stream with new parameters.
 |      
 |      This also does an implicit stream flush.
 |  
 |  seek(self, cookie, whence=0, /)
 |      Change stream position.
 |      
 |      Change the stream position to the given byte offset. The offset is
 |      interpreted relative to the position indicated by whence.  Values
 |      for whence are:
 |      
 |      * 0 -- start of stream (the default); offset should be zero or positive
 |      * 1 -- current stream position; offset may be negative
 |      * 2 -- end of stream; offset is usually negative
 |      
 |      Return the new absolute position.
 |  
 |  seekable(self, /)
 |      Return whether object supports random access.
 |      
 |      If False, seek(), tell() and truncate() will raise OSError.
 |      This method may need to do a test seek().
 |  
 |  tell(self, /)
 |      Return current stream position.
 |  
 |  truncate(self, pos=None, /)
 |      Truncate file to size bytes.
 |      
 |      File pointer is left unchanged.  Size defaults to the current IO
 |      position as reported by tell().  Returns the new size.
 |  
 |  writable(self, /)
 |      Return whether object was opened for writing.
 |      
 |      If False, write() will raise OSError.
 |  
 |  write(self, text, /)
 |      Write string to stream.
 |      Returns the number of characters written (which is always equal to
 |      the length of the string).
 |  
 |  ----------------------------------------------------------------------
 |  Static methods defined here:
 |  
 |  __new__(*args, **kwargs) from builtins.type
 |      Create and return a new object.  See help(type) for accurate signature.
 |  
 |  ----------------------------------------------------------------------
 |  Data descriptors defined here:
 |  
 |  buffer
 |  
 |  closed
 |  
 |  encoding
 |      Encoding of the text stream.
 |      
 |      Subclasses should override.
 |  
 |  errors
 |      The error setting of the decoder or encoder.
 |      
 |      Subclasses should override.
 |  
 |  line_buffering
 |  
 |  name
 |  
 |  newlines
 |      Line endings translated so far.
 |      
 |      Only line endings translated during reading are considered.
 |      
 |      Subclasses should override.
 |  
 |  write_through
 |  
 |  ----------------------------------------------------------------------
 |  Methods inherited from _IOBase:
 |  
 |  __del__(...)
 |  
 |  __enter__(...)
 |  
 |  __exit__(...)
 |  
 |  __iter__(self, /)
 |      Implement iter(self).
 |  
 |  readlines(self, hint=-1, /)
 |      Return a list of lines from the stream.
 |      
 |      hint can be specified to control the number of lines read: no more
 |      lines will be read if the total size (in bytes/characters) of all
 |      lines so far exceeds hint.
 |  
 |  writelines(self, lines, /)
 |      Write a list of lines to stream.
 |      
 |      Line separators are not added, so it is usual for each of the
 |      lines provided to have a line separator at the end.
 |  
 |  ----------------------------------------------------------------------
 |  Data descriptors inherited from _IOBase:
 |  
 |  __dict__