Reputation: 51
Whetever I do, I get this error when trying to print anything from 'ip_macAddr' using an index. Type is 'list' so I don't get why. The only explanation I have is that there's some type of caracter coming from the stdout of that subprocess that's messing things up.
Also I tried converting to string with no different result.
At this point I have ne clue. Thanks for your help!
Code
#!/usr/bin/env python3.7
import sys
import subprocess
import os
IP_NETWORK = '192.168.254.10'
IP_DEVICE = '192.168.254.194'
proc = subprocess.Popen(['ping', IP_NETWORK], stdout=subprocess.PIPE)
while True:
line = proc.stdout.readline()
# print(line)
if not line:
break
connected_ip = line.decode('utf-8').split()[3].replace(':','')
proc2 = subprocess.Popen(['ip', 'neigh', 'show', 'to', connected_ip], stdout=subprocess.PIPE)
ip_macAddr = proc2.stdout.readline().decode('utf-8').split()
print(connected_ip)
# print(type(ip_macAddr))
print(ip_macAddr[0])
Error
IndexError: list index out of range
edit 1
The output of print(ip_macAddr)
would be: ['192.168.254.10', 'dev', 'wlp61s0', 'lladdr', '88:88:a1:b2:c3:88', 'REACHABLE']
edit 2
print(type(ip_macAddr))
returns <class 'list'>
edit 3 Traceback
Traceback (most recent call last):
File "./device-connected-to-network.py", line 34, in <module>
print(ip_macAddr[0])
IndexError: list index out of range
This would happen using ANY index and I also tried using:
print(ip_macAddr[0])
or ip_macAddr = proc2.stdout.split()[0]
Again; same result using ANY index # and print(type(ip_macAddr))
returns type 'list'.
Another exemple;
The output of print(ip_macAddr)
is ['192.168.254.10', 'dev', 'wlp61s0', 'lladdr', '74:83:c2:d2:a4:12', 'REACHABLE']
.
So, if I do (in another file) - using index #4:
a = ['192.168.254.10', 'dev', 'wlp61s0', 'lladdr', '11:22:a1:b2:c3:33', 'REACHABLE']
print(type(a))
print(a[4])
The output is:
<class 'list'>
11:22:a1:b2:c3:33
So works as expected in this context, but not within the actual program.
Upvotes: 0
Views: 1201
Reputation: 189397
split()[3]
will fail with an IndexError
on any line which has less than four whitespace-separated fields.
A common fix is to simply skip lines with fewer fields.
Similarly, if ip
produces an empty string, splitting it produces an empty list, which you can't get the first element of.
You can also simplify your code by passing in text=True
, and use subprocess.run()
where you don't particularly need Popen()
. I have also removed unused import
s.
#!/usr/bin/env python3.7
import subprocess
IP_NETWORK = '192.168.254.10'
IP_DEVICE = '192.168.254.194'
proc = subprocess.Popen(['ping', IP_NETWORK],
stdout=subprocess.PIPE, text=True)
while True:
line = proc.stdout.readline()
# print(line)
if not line:
break
fields = line.split()
if len(fields) < 4:
continue
connected_ip = fields[3].replace(':','')
proc2 = subprocess.run(
['ip', 'neigh', 'show', 'to', connected_ip],
capture_output=True, text=True)
result = proc2.stdout
if not result:
continue
ip_macAddr = result[0]
print(connected_ip)
# print(type(ip_macAddr))
print(ip_macAddr)
Even better, trap and report any exceptions.
try:
proc2 = subprocess.run(
['ip', 'neigh', 'show', 'to', connected_ip],
capture_output=True, text=True,
check=True) # important
result = proc2.stdout
except CalledProcessError as exc:
print('`ip\' for', connected_ip, 'failed:', exc)
continue
Upvotes: 1