FatherPhipps
FatherPhipps

Reputation: 39

.index can't see an item in a list

New to the index function. I am trying to display the hostname and IP address of my PC, but I'm stuck at this index part. If I comment it out and print the whole list, what I'm looking for is right there. So why can't .index see it?

#!/usr/bin/python3.6

import socket 
import string
import subprocess
import tkinter
from tkinter import *

hostname = socket.gethostname()

arg='ip route list'    
p=subprocess.Popen(arg,shell=True,stdout=subprocess.PIPE)
data = p.communicate()
sdata = data[0].split()
ipaddr = sdata[ sdata.index('src')+1 ]


root = tkinter.Tk()
root.title(hostname)

L1 = Label(root, text=ipaddr)
L1.grid(row=1,column=2,sticky=W+E,padx=100,pady=10)

root.mainloop()

Contents of sdata:

[b'default', b'via', b'10.30.5.1', b'dev', b'ens33', b'proto', b'dhcp', 
b'metric', b'100', b'10.30.5.0/24', b'dev', b'ens33', b'proto', b'kernel', 
b'scope', b'link', b'src', b'10.30.5.7', b'metric', b'100', b'169.254.0.0/16', 
b'dev', b'ens33', b'scope', b'link', b'metric', b'1000']

Upvotes: 2

Views: 47

Answers (1)

cody
cody

Reputation: 11157

Take a look at what is returned by p.communicate():

>>> p=subprocess.Popen(arg,shell=True,stdout=subprocess.PIPE)
>>> data = p.communicate()
>>> data
(b'default via 107.170.96.1 dev eth0 onlink \n10.8.0.0/24 via 10.8.0.2 dev tun0 \n10.8.0.2 dev tun0 proto kernel scope link src 10.8.0.1 \n107.170.96.0/20 dev eth0 proto kernel scope link src 107.170.105.131 \n', None)

Note the b prefixing the stdout output, this means it is not a Unicode-encoded string, but rather a sequence of bytes. This is called out in the documentation for POpen.communicate

communicate() returns a tuple (stdout_data, stderr_data). The data will be strings if streams were opened in text mode; otherwise, bytes.

When you split data, it will thus return a list of byte sequences (see how each item is also prefixed with b?):

>>> sdata = data[0].split()
>>> sdata
[b'default', b'via', b'107.170.96.1', b'dev', b'eth0', b'onlink', b'10.8.0.0/24', b'via', b'10.8.0.2', b'dev', b'tun0', b'10.8.0.2', b'dev', b'tun0', b'proto', b'kernel', b'scope', b'link', b'src', b'10.8.0.1', b'107.170.96.0/20', b'dev', b'eth0', b'proto', b'kernel', b'scope', b'link', b'src', b'107.170.105.131']

What you're passing to index, 'src', is a string, not a byte sequence. These two are not equal:

>>> 'src' == 'src'
True
>>> 'src' == b'src'
False

So, one solution to your problem is to pass the byte sequence b'src' to index:

>>> sdata.index(b'src')
18 

See this SO question for further information.

Upvotes: 3

Related Questions