Based on this answer and the fact that list comprehensions no longer "leak" their variable in Python 3.x how I can implement/rewrite this expression in 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
First, that list comprehension is pretty whack stylistically. Totally incomprehensible for anyone trying to read it. Indentation is your friend, and numbers of lines of code are not a premium. Changing the indentation to make it more readable:
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()])
]
The problem now becomes clear. List comprehensions do not leak their scope in Python 3. Outside of the ports
list comprehension (if it didn't fail due to a NameError
), there would be no object called proc
.
That said, you do get a name error because the list comprehension inside your call to any
also doesn't leak its scope. No port
variable escapes outside to the parent list comprehension, and you get a NameError
.
Second, to address your question, you should probably avoid a list comprehension altogether. You're trying to do too much in a single statement. Create a ports
list. Iterate through your processes in a for
loop, and append
according to your required logic.
To demonstrate:
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)
Here, I've assumed that you wanted all ports for a given process if any of the ports match your given criterion, and you otherwise want none of them. This is how I read your comprehension. If that's not what you're looking for, then I can change it. (This is a concrete example of why using large list comprehensions should be avoided.)
Rather than using any
and expecting the list comprehension variable to leak out, you can find the relevant ports using properly qualified comprehensions.
I've separated it into two comprehensions so it would fit in my brain.
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)
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.