見出し画像

pythonプログラムの初歩12/ファイルアクセス権限を確認しよう。

こんにちはmakokonです。
今日はファイルのアクセス権限を確認するpythonプログラムです。
今日のエラーはこれ。めったに出ないのですが、出ると鬱陶しいし、たいていは容赦なくプログラムが止まるのでとても迷惑ですね。

PermissionError: [Errno 13] Permission denied:  ファイルの名前


ファイルのアクセス権限とは?

概要

  • ファイルのアクセス権限は、誰がどのようにファイルにアクセスできるかを制御するための設定です。


アクセス権限の種類

読み取り権限 (Read)

  • ファイルの内容を見ることができる。

書き込み権限 (Write)

  • ファイルの内容を変更できる。

実行権限 (Execute)

  • プログラムファイルやスクリプトを実行できる。


アクセス権限の対象

ユーザー (User)

  • ファイルの所有者。

  • 一般的にはファイルを作成した人。

グループ (Group)

  • ユーザーが所属するグループ。

  • グループ内の全員が同じ権限を持つ。

その他 (Others)

  • 上記以外の全てのユーザー。

  • ファイルを共有する場合に設定。


lsコマンドで確認してみます。


$ ls -ld test*/
drwxr-xr-x 2 xxxxxxx docker 4096  7月 19 17:11 test_a/
dr--r--r-- 2 xxxxxxx docker 4096  7月 19 17:11 test_b/

test_a,test_bディレクトリがあって、test_aはユーザーが読み込み、書き込み、実行が可能です。それに対して、test_bには読み込み権限しかありません。これがどういうことかというと、test_bがあることは見えるのですが、その中身を見ようとしても、書き込もうとしても、移動しようとしても拒否されます。
だから、「プログラム中でディレクトリやファイルを操作しようとして、権限がないと大変なことになるから確認しようね。」ということです。

$ ls test_b    
ls: fts_read: Permission denied
$ touch test_b/testx.txt
touch: test_b/testx.txt: Permission denied
$ cd test_b       
pushd: permission denied: test_b

どうしてpythonで確認するの

すでに述べたようにlsコマンドを使えば、状態はすぐに分かります。確認の手間も大したことはありません。なのに、どうしてpythonで確認しようとするのか。それは、自分のプログラムを使うのが自分だけではないから。そして他人の環境をすべて想定するのが難しいから。もっというと、使った人も、もらったプログラムをコピーして使うだけで、ファイル権限の問題があるなんて想像していないし、自分の環境を把握しているとは限らないから。
だから、実行プログラムは怪しいところは事前に確認して対処しておくほうがいいんです。

確認すべき内容とは

では、何を確認するか整理しましょう。
ファイルやディレクトリ操作でエラーが出るときというのは、だいたい次の3つをチェックすれば大丈夫です。

  • 目的のファイルやディレクトリが存在しない。

  • 目的のファイルやディレクトリを操作する権限がない。

  • 目的のファイルやディレクトリが別のアプリケーションが使用中でロックされている。

1つ目はわかりますね。コピーコマンドとかで"No such file or directory"とか言われるやつです。
2つ目は、すでに言いました。"permission denied"です。
そして、3つ目はあまり出会わないかもしれません。クラウド上のファイルをワードで編集しようとしたら"誰かが編集中です"とか言われるイメージだとわかりやすいでしょうか。つまり、ある種のアプリケーションは自分が使用しているファイルを勝手に操作されないように他のアクセスを禁止する事があるんです。
恥ずかしながら、makokonは、リリース前のアプリでは、一時ファイルとして"image.tmp"とかいう一時ファイルをよく使うのですが、この種のアプリを2つ立ち上げて、謎のエラーに悩まされました。名前からわかるようにこのファイルは書き換え作業を含むので、2番目のアプリは見事ロックされていて使えなかったわけです。もちろんエラーを見て、権限を確認しましたが、そのときは実行していないので問題ないわけで見えにくいエラーになりました。(この記事を書こうと思ったきっかけです)

確認コード

というわけで、pythonでファイルの存在、ファイルの権限、ファイルの使用(ロック)状況を確認します。
準備 ライブラリのインストール

pip install psutil

psutilは、システムのプロセスやリソースの情報を取得するためのPythonモジュールです。このプログラムでは、特定のファイルがどのプロセスによってロックされているかを確認するために使用されています。
このプログラムは、pythonを実行しているユーザー名、ファイルの存在、ファイルの権限、ファイルのロック状況を確認します。確認大正のファイルは中に書き込んでいるので、必要に応じて変更してください。



import os
import psutil

# 実行ユーザーを確認
user = os.getlogin()
print(f"Current user: {user}")

files = ["./test_a","./test_b"]
for file_path in files:

    # ファイルが存在するか確認
    if os.path.exists(file_path):
        print(f"File exists: {file_path}")
    else:
        print(f"File does not exist: {file_path}")

    # ファイルへのアクセス権を確認
    if os.access(file_path, os.R_OK):
        print(f"File is readable: {file_path}")
    else:
        print(f"File is not readable: {file_path}")

    # 書き込み権限を確認
    if os.access(file_path, os.W_OK):
        print(f"File is writable: {file_path}")
    else:
        print(f"File is not writable: {file_path}")
    
    # 実行権限を確認
    if os.access(file_path, os.X_OK):
        print(f"File is executable: {file_path}")
    else:
        print(f"File is not executable: {file_path}")


    locked = False

    for proc in psutil.process_iter(['pid', 'name']):
        try:
            for item in proc.open_files():
                if file_path == item.path:
                    print(f"Process {proc.info['name']} (PID: {proc.info['pid']}) is locking the file.")
                    locked = True
        except (psutil.NoSuchProcess, psutil.AccessDenied):
            continue

    if not locked:
        print("No process is locking the file.")


このコードのポイントは以下の通りです:

  1. psutil.process_iter(['pid', 'name']):

    • システム上の全てのプロセスを取得します。

    • 各プロセスのPID(プロセスID)と名前を取得します。

  2. proc.open_files():

    • 特定のプロセスが開いているファイルのリストを取得します。

    • これにはファイルパスを含むオブジェクトが含まれます。

  3. if file_path == item.path:

    • 各プロセスが開いているファイルのパスと、確認したいファイルパスを比較します。

    • 一致する場合、そのプロセスがファイルをロックしていると判断します。

  4. 例外処理:

    • psutil.NoSuchProcess: プロセスが存在しなくなった場合に発生します。

    • psutil.AccessDenied: アクセスが拒否された場合に発生します。

    • これらの例外が発生した場合は、次のプロセスへ進みます。

これにより、特定のファイルが他のプロセスによってロックされているかどうかを確認できます。

実行結果

$ python check.py   
Current user: xxxxxxx <= your name?
File exists: ./test_a
File is readable: ./test_a
File is writable: ./test_a
File is executable: ./test_a
No process is locking the file.
File exists: ./test_b
File is readable: ./test_b
File is not writable: ./test_b
File is not executable: ./test_b
No process is locking the file.

これで確かに状況を確認することができました。

確認その後

状況を確認して、問題があったらどうしたらいいのでしょう。
それこそ、設計者に求められるところでしょう。今回の記事はそれを考える材料を確認するためのものです。
以下の方法は、健全なプログラマーとして決して推奨しませんが、一つの対策です

  • ファイルがない => ファイルを作成する。

  • 権限がない => ファイルのアクセス権限を変更する。

  • 他のファイルが使用中でロックされれいる。 => 他のプログラムを停止させる

状況をわきまえずにこんなことをすれば大災害が発生するかもしれませんね。
プログラムの目的と、節度をわきまえて、警告を出したり条件が揃うのをまったりするのが普通ですかね。

まとめ

ファイルのアクセス権限の問題は、基本的なことでありながら、状況によって非常に見通しの悪い、トラブルを呼び込むことがあります。
今回の記事では、プログラム実行中のその状況においてファイルアクセス権限を確認する方法を示しました。
デバッグのため、ユーザークレームに対応するため、知っておいて損はないので、エラートラップで埋め込むなり、こっそりオプション化するなりご検討ください。

ハッシュタグ

#Python
#プログラミング
#ファイルアクセス
#エラー処理
#PermissionError
#初心者
#プログラミング初心者
#Python初心者
#ファイル管理
#システム開発
#PythonTips
#コーディング
#プログラマー
#開発者ブログ
#Pythonコード
#エラートラブル
#プログラムデバッグ
#Python学習
#アクセス権限

タイトル画の説明 by GPT-4o

この画像は、ユーザーがコンピューターの前に座り、「Access Denied」と表示された画面を見て驚いた表情をしているシーンを描いています。画面にはシルエットの人物アイコンが表示されており、「Depame」というプログラムかシステムのウィンドウが開かれています。デスクにはペン立てとライトが置かれており、ユーザーは手を動かしながら、アクセスが拒否されたことに対し困惑や緊張感を抱いているように見えます。全体的な雰囲気は緊迫感があり、ユーザーが何か重要なアクセスを試みているが、うまくいっていない状況を示しています。



この記事が気に入ったらサポートをしてみませんか?