ファイル
Path
CLIパラメータに加えて、いくつかの種類の「ファイル」を宣言することもできます。
ヒント
ほとんどの場合、Path
を使用すれば問題ありません。
Path
を使用して、同じ方法でデータを読み書きできます。
違いは、これらの型はPythonのファイルライクオブジェクトを、PythonのPathの代わりに提供することです。
「ファイルライクオブジェクト」とは、以下のようにopen()
によって返されるのと同じタイプのオブジェクトです。
with open('file.txt') as f:
# Here f is the file-like object
read_data = f.read()
print(read_data)
ただし、特別なユースケースでは、これらの特別な型を使用する必要がある場合があります。たとえば、既存のアプリケーションを移行する場合などです。
FileText
読み込み¶
typer.FileText
は、テキストを読み込むためのファイルライクオブジェクトを提供します。そこから str
データを取得します。
これは、ファイルに英語以外の言語で書かれたテキストが含まれている場合でも、たとえば、text.txt
ファイルに次のような内容が含まれている場合でも、
la cigüeña trae al niño
たとえば、次のようなテキストを含む str
があります。
content = "la cigüeña trae al niño"
bytes
を持つ代わりに、たとえば、
content = b"la cig\xc3\xbce\xc3\xb1a trae al ni\xc3\xb1o"
ファイルライクオブジェクトのすべての正しいエディターサポート、属性、メソッドなどが得られます。
import typer
from typing_extensions import Annotated
def main(config: Annotated[typer.FileText, typer.Option()]):
for line in config:
print(f"Config line: {line}")
if __name__ == "__main__":
typer.run(main)
ヒント
可能な場合は、Annotated
バージョンを使用することをお勧めします。
import typer
def main(config: typer.FileText = typer.Option(...)):
for line in config:
print(f"Config line: {line}")
if __name__ == "__main__":
typer.run(main)
確認してください
// Create a quick text config
$ echo "some settings" > config.txt
// Add another line to the config to test it
$ echo "some more settings" >> config.txt
// Now run your program
$ python main.py --config config.txt
Config line: some settings
Config line: some more settings
FileTextWrite
¶
テキストを書き込むには、typer.FileTextWrite
を使用できます。
import typer
from typing_extensions import Annotated
def main(config: Annotated[typer.FileTextWrite, typer.Option()]):
config.write("Some config written by the app")
print("Config written")
if __name__ == "__main__":
typer.run(main)
ヒント
可能な場合は、Annotated
バージョンを使用することをお勧めします。
import typer
def main(config: typer.FileTextWrite = typer.Option(...)):
config.write("Some config written by the app")
print("Config written")
if __name__ == "__main__":
typer.run(main)
これは、次のような人間のテキストを書き込むためのものです。
some settings
la cigüeña trae al niño
...バイナリ bytes
を書き込むためではありません。
確認してください
$ python main.py --config text.txt
Config written
// Check the contents of the file
$ cat text.txt
Some config written by the app
技術的な詳細
typer.FileTextWrite
は単なる便利なクラスです。
これは、typer.FileText
を使用して mode="w"
を設定するのと同じです。 mode
については、以下で詳しく説明します。
FileBinaryRead
¶
バイナリデータを読み込むには、typer.FileBinaryRead
を使用できます。
そこから bytes
を受け取ります。
画像のようなバイナリファイルを読み込むのに便利です。
import typer
from typing_extensions import Annotated
def main(file: Annotated[typer.FileBinaryRead, typer.Option()]):
processed_total = 0
for bytes_chunk in file:
# Process the bytes in bytes_chunk
processed_total += len(bytes_chunk)
print(f"Processed bytes total: {processed_total}")
if __name__ == "__main__":
typer.run(main)
ヒント
可能な場合は、Annotated
バージョンを使用することをお勧めします。
import typer
def main(file: typer.FileBinaryRead = typer.Option(...)):
processed_total = 0
for bytes_chunk in file:
# Process the bytes in bytes_chunk
processed_total += len(bytes_chunk)
print(f"Processed bytes total: {processed_total}")
if __name__ == "__main__":
typer.run(main)
確認してください
$ python main.py --file lena.jpg
Processed bytes total: 512
Processed bytes total: 1024
Processed bytes total: 1536
Processed bytes total: 2048
FileBinaryWrite
¶
バイナリデータを書き込むには、typer.FileBinaryWrite
を使用できます。
それに bytes
を書き込みます。
画像のようなバイナリファイルを書き込むのに便利です。
.write()
メソッドには、str
ではなく bytes
を渡す必要があることに注意してください。
str
がある場合は、最初にエンコードして bytes
を取得する必要があります。
import typer
from typing_extensions import Annotated
def main(file: Annotated[typer.FileBinaryWrite, typer.Option()]):
first_line_str = "some settings\n"
# You cannot write str directly to a binary file, you have to encode it to get bytes
first_line_bytes = first_line_str.encode("utf-8")
# Then you can write the bytes
file.write(first_line_bytes)
# This is already bytes, it starts with b"
second_line = b"la cig\xc3\xbce\xc3\xb1a trae al ni\xc3\xb1o"
file.write(second_line)
print("Binary file written")
if __name__ == "__main__":
typer.run(main)
ヒント
可能な場合は、Annotated
バージョンを使用することをお勧めします。
import typer
def main(file: typer.FileBinaryWrite = typer.Option(...)):
first_line_str = "some settings\n"
# You cannot write str directly to a binary file, you have to encode it to get bytes
first_line_bytes = first_line_str.encode("utf-8")
# Then you can write the bytes
file.write(first_line_bytes)
# This is already bytes, it starts with b"
second_line = b"la cig\xc3\xbce\xc3\xb1a trae al ni\xc3\xb1o"
file.write(second_line)
print("Binary file written")
if __name__ == "__main__":
typer.run(main)
$ python main.py --file binary.dat
Binary file written
// Check the binary file was created
$ ls ./binary.dat
./binary.dat
ファイル CLIパラメータ 設定¶
typer.Option()
および typer.Argument()
で、これらの型(クラス)にいくつかの設定パラメータを使用できます。
mode
: ファイルを開く「モード」を制御します。- 上記のクラスを使用することで自動的に設定されます。
- 詳細については、以下をお読みください。
encoding
: 特定のエンコーディング(例:"utf-8"
)を強制します。lazy
: I/O 操作を遅延させます。デフォルトでは自動です。- デフォルトでは、ファイルを書き込むとき、Click はまだ実際のファイルではないファイルライクオブジェクトを生成します。書き込みを開始すると、ファイルが開かれ、書き込みが開始されますが、それまでは開始されません。これは、主に書き込みを開始するまでファイルの作成を回避するのに役立ちます。通常は、これを自動のままにしておく方が安全です。ただし、
lazy=False
を設定することで上書きできます。デフォルトでは、書き込みの場合はlazy=True
、読み込みの場合はlazy=False
です。
- デフォルトでは、ファイルを書き込むとき、Click はまだ実際のファイルではないファイルライクオブジェクトを生成します。書き込みを開始すると、ファイルが開かれ、書き込みが開始されますが、それまでは開始されません。これは、主に書き込みを開始するまでファイルの作成を回避するのに役立ちます。通常は、これを自動のままにしておく方が安全です。ただし、
atomic
: true の場合、すべての書き込みは実際には一時ファイルに行われ、完了後に最終的な宛先に移動されます。これは、複数のユーザー/プログラムによって頻繁に変更されるファイルで役立ちます。
高度な mode
¶
デフォルトでは、Typer はmode
を自動的に設定します。
typer.FileText
:mode="r"
、テキストを読み込みます。typer.FileTextWrite
:mode="w"
、テキストを書き込みます。typer.FileBinaryRead
:mode="rb"
、バイナリデータを読み込みます。typer.FileBinaryWrite
:mode="wb"
、バイナリデータを書き込みます。
FileTextWrite
についての注意¶
typer.FileTextWrite
は実際には単なる便利なクラスです。 typer.FileText
で mode="w"
を使用するのと同じです。
ただし、他のクラスと同様に、エディターで typer.File
... と入力するだけで自動補完で取得できるため、おそらく短く、より直感的です。
mode
のカスタマイズ¶
上記のデフォルトから mode
をオーバーライドできます。
たとえば、mode="a"
を使用して、同じファイルに「追加」書き込みを行うことができます。
import typer
from typing_extensions import Annotated
def main(config: Annotated[typer.FileText, typer.Option(mode="a")]):
config.write("This is a single line\n")
print("Config line written")
if __name__ == "__main__":
typer.run(main)
ヒント
可能な場合は、Annotated
バージョンを使用することをお勧めします。
import typer
def main(config: typer.FileText = typer.Option(..., mode="a")):
config.write("This is a single line\n")
print("Config line written")
if __name__ == "__main__":
typer.run(main)
ヒント
mode="a"
を手動で設定しているので、typer.FileText
または typer.FileTextWrite
を使用できます。どちらも機能します。
確認してください
$ python main.py --config config.txt
Config line written
// Run your program a couple more times to see how it appends instead of overwriting
$ python main.py --config config.txt
Config line written
$ python main.py --config config.txt
Config line written
// Check the contents of the file, it should have each of the 3 lines appended
$ cat config.txt
This is a single line
This is a single line
This is a single line
異なる型について¶
情報
これらは、Typer によって提供される異なる型/クラスの理由に関する技術的な詳細です。
ただし、これらを使用するためにこの情報は必要ありません。スキップできます。
Typer は、これらの異なる型(クラス)を提供します。なぜなら、それらは各ケースで下に提供される実際の Python 実装を直接継承しているからです。
これにより、エディターは各型に対して正しい型チェックと補完を提供します。
lazy
を使用する場合でも。 lazy
を使用すると、Click は書き込みを遅延させるための特別なオブジェクトを作成し、書き込まれる実際のファイルへの「プロキシ」として機能します。ただし、この特別なプロキシオブジェクトは、エディターでの型チェックと補完に必要な属性とメソッドを公開しません。これらの属性にアクセスしたり、メソッドを呼び出すと、「プロキシ」lazy オブジェクトは最終オブジェクトでそれらを呼び出し、すべてが機能します。ただし、それらに対する自動補完は得られません。
ただし、これらの **Typer** クラスは、下に提供される実際の実装(lazy オブジェクトではない)を継承しているため、エディターですべての自動補完と型チェックが得られます。