基于this的答案以及列表理解不再在Python 3.x中“泄漏”其变量的事实,如何在Python 3中实现/重写此表达式?
>>> import sys
>>> sys.version[:5]
'3.6.5'
>>> import psutil
>>> psutil.__version__
'5.4.7'
>>> [port.laddr.port for proc in psutil.process_iter(attrs=['name']) if 'sshd' in proc.info['name'] if any([port.status == psutil.CONN_LISTEN for port in proc.connections()])]
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "<stdin>", line 1, in <listcomp>
NameError: name 'port' is not defined
答案 0 :(得分:2)
首先,从风格上讲,列表理解很不明智。试图阅读它的人完全无法理解。缩进是您的朋友,而代码行的数量也不是问题。更改缩进使其更具可读性:
ports = [
port.laddr.port
for proc in psutil.process_iter(attrs=['name'])
if 'sshd' in proc.info['name']
if any([port.status == psutil.CONN_LISTEN for port in proc.connections()])
]
问题现在变得很清楚。列表推导不会泄漏其在Python 3中的作用域。在ports
列表推导之外(如果它不会由于NameError
而失败),将没有名为proc
的对象。
也就是说,您要做会收到名称错误,因为对any
的调用中的列表理解也不会泄漏其范围。没有port
变量会逃脱到父列表理解之外,而您会得到NameError
。
第二,要解决您的问题,您可能应该完全避免列表理解。您正在尝试在单个语句中做太多的事情。创建一个ports
列表。在for
循环中循环访问您的进程,并根据您需要的逻辑append
进行迭代。
演示:
ports = []
def validate_proc(proc):
return any(
port.status == psutil.CONN_LISTEN
for port in proc.connections()
)
for proc in in psutil.process_iter(attrs=['name']):
if not 'sshd' in proc.info['name']:
continue
if not validate_proc(proc):
continue
for port in proc.connections():
ports.append(port.laddr.port)
在这里,我假设如果任何个端口符合给定条件,则您想要给定进程的所有个端口,否则就不希望它们。这就是我阅读您的理解的方式。如果这不是您想要的,那么我可以更改它。 (这是为什么应避免使用大列表理解的具体示例。)
答案 1 :(得分:0)
您可以使用适当限定的理解来找到相关的端口,而不是使用any
并期望列表理解变量泄漏出去。
我将其分为两种理解,以便适合我的大脑。
procs = [proc for proc in psutil.process_iter(attrs=['name'])
if 'sshd' in proc.info['name']]
ports = [port.latter.port for proc in procs
for port in proc.connections() if port.status==psutil.CONN_LISTEN]
print(ports)