ファイル操作は、どのプログラミング言語でも習得すべき最も重要なスキルの1つであり、これを正しく行うことが最も重要です。間違うと、自分のプログラム、同じシステムで動作している他のプログラム、さらにはシステム自体にまで問題を引き起こす可能性があります。
親ディレクトリが存在しなかったり、他のプログラムがファイルシステム内のファイルを同時に変更したりすることで、レースコンディションと呼ばれるエラーが発生する可能性があります。
レースコンディション(この場合はデータレースと呼ばれます)は、2つ以上のプログラムが同じ場所に同じ名前のファイルを作成しようとするときに発生します。この種のバグが発生した場合、非決定論的、つまり簡単に言えば、データを奪い合う2つのレーサーの正確なタイミングによって異なることが起こりうるため、発見と修正が非常に困難です。
今回は、Pythonでサブディレクトリを安全な方法で作成する方法を、順を追って見ていきましょう。以後、全てはMac、Linux、Windowsで動作します。
pathlibによる安全なネストディレクトリの作成
サブディレクトリを作成する方法はたくさんありますが、おそらく最もシンプルな方法は pathlib
モジュールを使用することでしょう。pathlib` モジュールは主に、異なるオペレーティングシステムのファイルシステムを抽象化し、それらのほとんどを扱うための統一されたインターフェイスを提供するために作られています。
このモジュールのおかげで、あなたのコードはプラットフォームに依存しないはずです。このモジュールは新しいバージョンの Python (3.5 以降) でしか動作しないことに注意してください。
あるディレクトリの絶対パスが文字列として与えられていて、与えられた名前のサブディレクトリを作りたいとします。OuterDirectoryという名前のディレクトリを作成し、その中に
InnerDirectory` を配置することにしよう。
ここでは、 pathlib
モジュールから Path
をインポートし、新しいファイルのパスを指定して Path
オブジェクトを作成し、次のシグネチャを持つ mkdir()
メソッドを使用しています。
Path.mkdir(mode=0o777, parents=False, exist_ok=False)
次のコードは、上で説明したことを実行しています。
from pathlib import Path # Import the module
path = Path("/home/kristina/OuterDirectory/InnerDirectory") # Create Path object
path.mkdir() # Cake the directory
もし mkdir()
が成功しなかった場合は、ディレクトリは作成されず、エラーが発生します。
アクセス権限の割り当て
存在しないSecondOuterDirectory
の中に、所有者だけが読み書き実行の全ての権限を持つSecondInnerDirectory
というディレクトリを作ってみましょう。
Traceback (most recent call last):
File "makesubdir.py", line 3, in <module
path.mkdir()
File "/home/kristina/anaconda3/lib/python3.7/pathlib.py", line 1230, in mkdir
self._accessor.mkdir(self, mode)
FileNotFoundError: [Errno 2] No such file or directory: '/home/kristina/OuterDirectory/InnerDirectory'
これはエラーなしで実行されるはずです。もし、SecondOuterDirectory
に移動して、コンソールからその中身をチェックすると、次のようになります。
Traceback (most recent call last):
File "/home/kristina/Desktop/UNM/makesubdir.py", line 3, in <module
path.mkdir()
File "/home/kristina/anaconda3/lib/python3.7/pathlib.py", line 1230, in mkdir
self._accessor.mkdir(self, mode)
FileExistsError: [Errno 17] File exists: '/home/kristina/OuterDirectory/InnerDirectory'
このような出力が得られるはずです。
from pathlib import Path
path = Path("/home/kristina/OuterDirectory/InnerDir")
try:
path.mkdir()
except OSError:
print("Failed to make nested directory")
else:
print("Nested directory made")
さて、親ディレクトリが正常に作成されたことは確認できましたが、権限は期待通りではありません。所有者には書き込み権限がありません。
この問題は、umask
が必要な特権を作成させてくれないことにあります。これを回避するために、OSモジュールの umask()
メソッドを使用して、 umask
の元の値を保存し、一時的に変更し、最後に元の値に戻すことにします。umask()
は umask
の古い値を返します。
これをテストするために、コードを書き換えてみましょう。
Nested directory made
このコードを実行し、再び ls -al
コマンドを使用すると、次のような出力が得られます。
Failed to make a nested directory
結論
多くの異なるシステム上で安全にファイルを操作するためには、データ競合のようなエラーを処理する堅牢な方法が必要です。Python は pathlib
モジュールを通して、このための素晴らしいサポートを提供しています。
ファイルシステムを操作するときには常にエラーが発生する可能性があり、これに対処する最善の方法は、プログラムをクラッシュさせたり他の問題を引き起こす可能性のあるすべてのエラーをキャッチするシステムを注意深くセットアップすることです。きれいなコードを書くことは、耐久性のあるプログラムを作ることになります。
</module