質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.37%
Windows 10

Windows 10は、マイクロソフト社がリリースしたOSです。Modern UIを標準画面にした8.1から、10では再びデスクトップ主体に戻され、UIも変更されています。PCやスマホ、タブレットなど様々なデバイスに幅広く対応していることが特徴です。

Python 3.x

Python 3はPythonプログラミング言語の最新バージョンであり、2008年12月3日にリリースされました。

Q&A

解決済

1回答

6500閲覧

windowsで実行中のプロセスのフルパスを、pythonから調べたい

退会済みユーザー

退会済みユーザー

総合スコア0

Windows 10

Windows 10は、マイクロソフト社がリリースしたOSです。Modern UIを標準画面にした8.1から、10では再びデスクトップ主体に戻され、UIも変更されています。PCやスマホ、タブレットなど様々なデバイスに幅広く対応していることが特徴です。

Python 3.x

Python 3はPythonプログラミング言語の最新バージョンであり、2008年12月3日にリリースされました。

0グッド

1クリップ

投稿2019/03/28 02:39

課題

pythonのアプリを開発しています。
ユーザーがアプリを重複起動しないように管理したいというのが課題です。

app_main.pyからアプリが起動されるとすると、既にapp_main.pyのプロセスがある場合には、
新たにapp_main.pyを実行しても起動させない(exitさせる)、ということを考えています。

やったこと

その1

コマンドで、tasklistを実行すると、プロセス一覧が出ると思います。
subprocess.run("tasklist")
を実行すれば、pythonでタスク一覧は取得できました。

ただこれだと、

python.exe 3000 Console 1 20,000 K

というような表記になり、どのファイルが実行されているのかが区別できません。

その2
os.getpid()を使って、プロセスIDは取得できます。
ですので、プロセスIDをテキストファイルにログとして残す&終了したらログは消す、というような管理方法も一応試しました。
しかしこれだと、pythonが正常終了しなかった場合に、ログにそのままIDが残りますので、あまり信頼できないと思いました。

その3
起動時に、自分以外のpythonプロセスを全て終了させる、という案も考えました。しかし乱暴すぎると思ってやっていません。

質問

あれこれ考えた結果では、やはりpython.exeがどのパスから起動されているかを判別するのが一番話が早いように思えました。
どのようにすればよいのでしょうか。
よろしくお願いいたします。

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答1

0

ベストアンサー

実行中の各プロセスの情報を得たいのであれば、 psutil モジュールを利用するのが楽なのではないでしょうか。次のようにして、プロセスの列挙と実行パスの取得が可能です。

python

1import psutil 2 3for proc in psutil.process_iter(): 4 print('-' * 30) 5 print(f'プロセス ID: {proc.pid}') 6 7 try: 8 print(f'実行モジュール: {proc.exe()}') 9 print(f'コマンドライン: {proc.cmdline()}') 10 print(f'カレントディレクトリ: {proc.cwd()}') 11 except psutil.AccessDenied: 12 print('(このプロセスへのアクセス権がありません)')

ただ、実現したい目的が 「同じスクリプトの多重起動を防止する」ことなのであれば、別の手段を取った方が楽 なように思われます。

具体的には一例として、 Mutex のような カーネルオブジェクトを名前付きで作成し、「既に同じ名前のオブジェクトが存在する場合」には処理を中断する 、といったやりかたが古来から使われています。このようなカーネルオブジェクトは、プロセスの終了時に OS によって CloseHandle されることが保証されている為、エラー終了を気にする必要も御座いません。pywin32 を使用して、次のような実装になるでしょうか。

python

1import sys 2import win32api 3import win32event 4import winerror 5import pywintypes 6 7UNIQUE_MUTEX_NAME = 'Global\MyProgramIsAlreadyRunning' 8 9handle = win32event.CreateMutex(None, pywintypes.FALSE, UNIQUE_MUTEX_NAME) 10 11if not handle or win32api.GetLastError() == winerror.ERROR_ALREADY_EXISTS: 12 print('既に別のプロセスが実行中です。', file=sys.stderr) 13 sys.exit(-1) 14 15print('このプロセスだけが実行中です。') 16input()

但し、仕組みから明らかなように、この場合は Mutex の名前が一致するスクリプトの同時起動を防ぐ ことになるので、例えば同じスクリプトを別のフォルダにコピーした場合も、 コピー元とコピー先を同時に起動することは出来なくなります

もし今回、 「あくまでスクリプトの実行パスをキーにして多重起動を防止すること」 が重要なのであれば、最初に掲示した psutil を用いるか、あるいはパスに含まれる文字列を Mutex 名に組み込むような応用をなさるのが宜しいかと存じます。

投稿2019/03/28 04:23

編集2019/03/28 06:05
argparse

総合スコア1017

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

退会済みユーザー

退会済みユーザー

2019/03/29 12:51

ご丁寧にありがとうございます! Mutexの方式も含めて試してみたいと思います。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.37%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問