views:

220

answers:

2

Hi Pythoners.

This snippet gets me the dotted quad of my BSD network interface. I would like to figure out how to use the subprocess module instead.

ifcfg_lines = os.popen("/sbin/ifconfig fxp0").readlines()
x = string.split(ifcfg_lines[3])[1]

Seems as if I can't use subprocess in exactly the same way. I don't think I want shell=True or PIPE. What should I do to make the output indexable?

Thanks.

A: 

Why not use something like:

import socket
ipadr = socket.gethostbyname(socket.gethostname())

as in Finding Local IP Addresses in Python and remove the subprocess dependency? There are also some other suggestions in that question.

I also found a post on the netifaces package that does aims to do this with better cross-platform support.

Dana the Sane
Heh. I was using the socket module in a less elegant way but discovered that I was getting the wrong IP back because of DNS.The server is a domestic broadband network client so DNS is going to be wrong unless my dyndns.org hostname is resolving correctly which it is not.
Fair enough, I wondered if that was why you were getting the ip by device name. How about the netifaces approach? It uses system calls instead of dns.
Dana the Sane
I had been doing this: CURRENT = socket.getaddrinfo(socket.gethostname(), None)[0][4][0]For whatever reason, the above (and your) syntax gets back 173.48.208.152 while /sbin/ifconfig fxp0 renders: 173.48.204.168 .
I am not familiar with netifaces.
+1  A: 
from subprocess import Popen, PIPE

ifcfg_lines = Popen("/sbin/ifconfig fxp0",shell=True,stdout=PIPE).stdout.readlines()
x = string.split(ifcfg_lines[3])[1]

For a little more elegance, hide the details:

def getBSDIP():
   from subprocess import Popen, PIPE
   import string

   CURRENT = Popen("/sbin/ifconfig fxp0", shell=True,stdout=PIPE).stdout.readlines()
   return(string.split(CURRENT[3])[1])

If you are going to use subprocess to do this then elegance is a bit limited because you are essentially doing something like screenscraping, except here you are scriptscraping. If you want a truly general solution, use the socket library, i.e. let Python handle the portability.

Often, when you look at a bit of code and you wish that there was a better cleaner way to do it, this means that you need to question your assumptions, and change the algorithm or architecture of the solution.

Michael Dillon
you need to import PIPE too
gnibbler
Uh. Yeah. I don't seem to have a PIPE module. Where the hell does PIPE come from?
http://docs.python.org/library/subprocess.html talks about "stdin=PIPE and stdout=PIPE must be specified."So I do specify them and python doesn't know wtf I'm talking about :)
`from subprocess import Popen,PIPE`
gnibbler
Oh, it works if I use subprocess.PIPE. Dumb.
Really? Why should I need to specify it? Rhetorical question. I know you are not Guido.
CURRENT = Popen("/sbin/ifconfig fxp0", shell=True,stdout=PIPE).stdout.readlines()This works and x = string.split(CURRENT[3])[1] can now get the correct IP address. But is there a more elegant way?
you should use something like lines, errors = Popen(['/sbin/ifconfig', 'fxp0'],....).communicate(). Otherwise you can catch a sigpipe on a long program output and introduce incorrectly quoted arguments.
abbot