【问题标题】:How to find pid of a process by Python?如何通过Python查找进程的pid?
【发布时间】:2020-09-04 08:56:42
【问题描述】:

朋友:

我在 Linux 中运行一个脚本:

我可以使用ps命令获取进程。

ps -ef | grep "python test09.py&"

但是,我如何使用python代码通过给定关键字python test09.py&知道运行脚本的pid?


EDIT-01

我的意思是,我想用python脚本找到运行脚本python test09.py&的pid。


EDIT-02

当我运行 anali 的方法时,我会得到这个错误:

Traceback (most recent call last):
  File "/Library/Frameworks/Python.framework/Versions/3.5/lib/python3.5/site-packages/psutil/_psosx.py", line 363, in catch_zombie
    yield
  File "/Library/Frameworks/Python.framework/Versions/3.5/lib/python3.5/site-packages/psutil/_psosx.py", line 429, in cmdline
    return cext.proc_cmdline(self.pid)
ProcessLookupError: [Errno 3] No such process (originated from sysctl)

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "test11.py", line 29, in <module>
    print(get_pids_by_script_name('test09.py'))
  File "test11.py", line 15, in get_pids_by_script_name
    cmdline = proc.cmdline()
  File "/Library/Frameworks/Python.framework/Versions/3.5/lib/python3.5/site-packages/psutil/__init__.py", line 694, in cmdline
    return self._proc.cmdline()
  File "/Library/Frameworks/Python.framework/Versions/3.5/lib/python3.5/site-packages/psutil/_psosx.py", line 342, in wrapper
    return fun(self, *args, **kwargs)
  File "/Library/Frameworks/Python.framework/Versions/3.5/lib/python3.5/site-packages/psutil/_psosx.py", line 429, in cmdline
    return cext.proc_cmdline(self.pid)
  File "/Library/Frameworks/Python.framework/Versions/3.5/lib/python3.5/contextlib.py", line 77, in __exit__
    self.gen.throw(type, value, traceback)
  File "/Library/Frameworks/Python.framework/Versions/3.5/lib/python3.5/site-packages/psutil/_psosx.py", line 376, in catch_zombie
    raise AccessDenied(proc.pid, proc._name)
psutil.AccessDenied: psutil.AccessDenied (pid=1)

【问题讨论】:

  • 请您澄清一下您要在这里做什么。您是想找出 same python 进程中的 pid(只需使用os.getpid())还是试图找出 another python 进程的 pid命令行?如果是第二个选项,那么它始终是 您的 进程之一,还是由另一个用户运行的进程?
  • 我要查找运行脚本的pid。比如我可以使用ps -ef | grep xxx

标签: python pid


【解决方案1】:

如果你只想要当前脚本的pid,那么使用os.getpid:

import os
pid = os.getpid()

但是,下面是使用psutil 查找运行命名python 脚本的python 进程的pid 的示例。这可能包括当前进程,但主要用例是检查 other 进程,因为对于 current 进程,使用os.getpid 更容易,如上所示。

sleep.py

#!/usr/bin/env python
import time
time.sleep(100)

get_pids.py

import os
import psutil


def get_pids_by_script_name(script_name):

    pids = []
    for proc in psutil.process_iter():

        try:
            cmdline = proc.cmdline()
            pid = proc.pid
        except psutil.NoSuchProcess:
            continue

        if (len(cmdline) >= 2
            and 'python' in cmdline[0]
            and os.path.basename(cmdline[1]) == script_name):

            pids.append(pid)

    return pids


print(get_pids_by_script_name('sleep.py'))

运行它:

$ chmod +x sleep.py

$ cp sleep.py other.py

$ ./sleep.py &
[3] 24936

$ ./sleep.py &
[4] 24937

$ ./other.py &
[5] 24938

$ python get_pids.py 
[24936, 24937]

【讨论】:

  • 你的方式行得通。但应该除外更多:[psutil.NoSuchProcess, psutil.AccessDenied,]
  • @244boy 我不相信捕获psutil.AccessDenied 是必要的。它只是试图阅读/proc/&lt;pid&gt;/cmdline,这是世界可读的。如果尝试提取例如受保护的环境变量(取决于对/proc/&lt;pid&gt;/environ 的访问),那将是另一回事。
  • 一般来说,我不喜欢捕获除了有理由相信应该发生的异常之外的异常,因为这样做可以隐藏错误。捕获psutil.NoSuchProcess 的原因是为了以防有一个进程在迭代它们所需的短时间内终止(如果父进程确实仍然存在,父进程有waited)。
  • 我还看到另一个答案也捕获了psutil.ZombieProcess。我不确定在什么情况下会引发异常,但我已经测试了访问 proc.pidproc.cmdline() 的僵尸进程不会引发任何异常。
【解决方案2】:

使用此代码并针对 cmd 行进行字符串匹配

import psutil
# Iterate over all running process
for proc in psutil.process_iter():
    try:
        # Get process name & pid & cmd line from process object.
        processName = proc.name()
        processID = proc.pid
        print(proc.cmdline())
        print(processName , ' ::: ', processID)
    except (psutil.NoSuchProcess, psutil.AccessDenied, psutil.ZombieProcess):
        pass

【讨论】:

    【解决方案3】:

    使用子进程库

    导入子流程 script_name = "test09.py" ps_out = subprocess.Popen("ps -ef".split(' '), stdout=subprocess.PIPE, stderr=subprocess.PIPE).stdout.read().decode('UTF-8').split("\ n") # 启动命令行并收集输出 for entry in ps_out: # 遍历返回的 ps 行 如果 script_name 在条目中: script_pid = entry.split()[1] # 检索行中的第二个条目 休息 打印(script_pid)

    【讨论】:

    • 是的,管道符号'|'不接受使用子流程。使用 grep 命令的 for 循环。 @244boy
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-03-06
    • 2014-12-28
    • 1970-01-01
    • 2016-05-08
    相关资源
    最近更新 更多