Python:从列表理解(psutil)中获取唯一值

Python:从列表理解(psutil)中获取唯一值,python,psutil,Python,Psutil,我想从psutil获取唯一的进程名称、PID和侦听端口 我目前拥有以下代码: names, pids, ports = zip(*[( proc.info['name'], proc.info['pid'], port.laddr.port) for proc in psutil.process_iter(attrs=['name', 'pid']) if 'java' in proc.info['name'] for port in proc.conne

我想从
psutil
获取唯一的进程名称、PID和侦听端口

我目前拥有以下代码:

names, pids, ports = zip(*[(
    proc.info['name'],
    proc.info['pid'],
    port.laddr.port)
    for proc in psutil.process_iter(attrs=['name', 'pid']) if 'java' in proc.info['name']
    for port in proc.connections() if port.status == psutil.CONN_LISTEN
])
问题是进程名称和PID被复制以匹配嵌套for循环(端口)中的项目数:

我想我可以在事后将它们转换成
集,但我希望有一种更好、更具python风格的方法来实现,而不会浪费资源

更新:2018年10月11日星期四14:36:33 UTC

根据@Rouven B的回答,我现在得到了以下代码:

names = set()
pids = set()
ports = set()
for proc in psutil.process_iter(attrs=['name', 'pid']):
    if 'java' not in proc.info['name']:
        continue
    names.add(proc.info['name'])
    pids.add(proc.info['pid'])
    for port in proc.connections():
        if port.status == psutil.CONN_LISTEN:
            ports.add(port.laddr.port)

但我仍然想知道是否还有其他方法,也许可以使用?

中的一个函数这里是一个列表理解,以消除重复项

names, pids, ports = zip(*[
    (proc.info['name'], proc.info['pid'], port.laddr.port)
    for proc in psutil.process_iter(attrs=['name', 'pid']) if 'java' in proc.info['name']
    if any([port.status == psutil.CONN_LISTEN for port in proc.connections()])
]*)
但这并不容易阅读。这个怎么样

names = []
pids = []
ports = []
for proc in psutil.process_iter(attrs=['name', 'pid']):
    if 'java' not in proc.info['name']:
        continue
    for port in proc.connections():
        if port.status == psutil.CONN_LISTEN:
            names.append(proc.info['name'])
            pids.append(proc.info['pid'])
            ports.append(port.laddr.port)
            break
但是我想说,使用
set
消除重复项也是一个非常好的解决方案。它不应该太慢,也不会改变算法的时间复杂度(以O为单位)

编辑:我误解了你想要实现的目标。下面是另一种紧凑的方法(仍然不是真正可读的)


我认为使用集合是获得唯一列表的一种非常好的方法。您还可以使用for循环,而不是列表理解和
break
,只要找到连接的端口。这样,每个进程只需添加一次。谢谢您的帮助。您的第一个解决方案将返回一个可以处于任何状态的随机端口,但我需要所有收集的进程的所有
侦听端口。您的理解列表也会将输出更改为:
[('name',PID,random port),(…)]
但我需要将它们组合在一起:
[('name'),(PID),(port)]
哦,似乎我误解了您要解决的问题。我添加了一个新的理解列表,它可以满足您的需求。但是,如果进程具有相同的名称,则仍然可能存在重复。为了摆脱这些,你应该使用集合。
names = []
pids = []
ports = []
for proc in psutil.process_iter(attrs=['name', 'pid']):
    if 'java' not in proc.info['name']:
        continue
    for port in proc.connections():
        if port.status == psutil.CONN_LISTEN:
            names.append(proc.info['name'])
            pids.append(proc.info['pid'])
            ports.append(port.laddr.port)
            break
names, pids, ports = zip(*[(
    proc.info['name'],
    proc.info['pid'],
    [conn.laddr.port for conn in proc.connections()
     if conn.status == psutil.CONN_LISTEN])
    for proc in psutil.process_iter(attrs=['name', 'pid'])
    if 'java' in proc.info['name']
])
ports = list(sum(o, ()))  # flatten list of lists of ports