Mailing List Archive

What's a good way to get my IP from Python?
Hello,

Does anyone know of a really good way to determine the
IP address of the ethernet cards on a Linux system
using Python only (i.e. no C code/parsing external binaries, etc.) ?

Thanks in advance,

Aaron

--
Aaron Rhodes
Network Security Engineer
aarhodes@cisco.com
(512) 378-1097
What's a good way to get my IP from Python? [ In reply to ]
Aaron Rhodes <aarhodes@cisco.com> wrote:
: Hello,

: Does anyone know of a really good way to determine the
: IP address of the ethernet cards on a Linux system
: using Python only (i.e. no C code/parsing external binaries, etc.) ?

Hopefully this is portable, but my work PC is down and don't have
access to a Mac; but theoretically it should be.

import socket
def my_ipaddr(interface_hostname=None):
# give the hostname of the interface you want the ipaddr of
hostname = interface_hostname or socket.gethostname()
s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
s.bind(hostname, 0)
ipaddr, port = s.getsockname()
s.close()
return ipaddr # returns 'nnn.nnn.nnn.nnn' (StringType)

You aren't connecting to anything so this _should_ work even if you are
not on a network at the time (PPP), the interface just needs to be
plumbed and initialized. The begged question would be: how do you get
the hostnames of multiple interfaces from within Python. Anyone have a
good answer for that?

-Arcege
What's a good way to get my IP from Python? [ In reply to ]
Aaron Rhodes writes:
> Hello,
>
> Does anyone know of a really good way to determine the
> IP address of the ethernet cards on a Linux system
> using Python only (i.e. no C code/parsing external binaries, etc.) ?
>

How about this? I don't know if it's "really good" but it works, and
it shows you how to do IOCTL's from Python. (Lately, folks on the
list have been suggesting writing a new extension module whenever you
need to do such a thing, but this is IMO unattractive from the point
of view of easy redistribution of code).

The only external dependency is on the file /proc/net/dev to get the
names of all present network interfaces. (This will also pick up
loopback, dummy, ppp, and any other interface types). If you know you
are only interested in eth*, you could just use a loop where ifname
goes from eth0 to ethN (assuming you don't have more than N NIC's) and
just catch exceptions where there is "no such device". However, since
you said you are interested in Linux, /proc/net/dev is a pretty
reasonable thing to look at. The linux "ifconfig -a" command gets its
interface list the same way.

There are some hardcoded constants in the code below. 32 is the size
of "struct ifreq" (see /usr/include/linux/if.h) and 20:24 are the
offsets of the inet address within this structure

These offsets are correct for kernel 2.2. These offsets will need to
be tweaked for older kernel versions. To create a truly portable
version of this code, you'd have to look at os.uname()[3] and adjust
the offsets appropriately.

A purist would probably use the struct module rather than slicing
strings.




#!/usr/bin/env python

import string
import socket
import fcntl
import IN

iflist = open("/proc/net/dev").readlines()

s=socket.socket(socket.AF_INET,socket.SOCK_STREAM)

for line in iflist:
if ':' not in line:
continue
words=string.split(line,':')
ifname, rest = words[0],words[1:]
ifname = string.strip(ifname)

print ifname,

ifr = ifname+'\0'*(32-len(ifname))
r= fcntl.ioctl(s.fileno(),IN.SIOCGIFADDR,ifr)
addr = map(ord,r[20:24])

print addr
What's a good way to get my IP from Python? [ In reply to ]
A correction to the code I posted earlier: change

ifr = ifname+'\0'*(32-len(ifname))

to

ifr = ifname+'\0'*(16-len(ifname))+chr(socket.AF_INET)+15*'\0'


As Aaron Rhodes pointed out to me, the version I originally posted
won't work on Linux 2.0 kernels. It seems that the SIOCGIFADDR ioctl
wants to have the address family in the struct ifrequest on older
kernels, whereas kernel 2.2 doesn't care. With the correction above,
the code I posted will work on either 2.0 or 2.2. Also, there are no
differences in the struct ifreq, so no "offset tweaking" is necessary.
What's a good way to get my IP from Python? [ In reply to ]
"Michael P. Reilly" <arcege@shore.net> writes:
| Aaron Rhodes <aarhodes@cisco.com> wrote:
| : Does anyone know of a really good way to determine the
| : IP address of the ethernet cards on a Linux system
| : using Python only (i.e. no C code/parsing external binaries, etc.) ?
|
| Hopefully this is portable, but my work PC is down and don't have
| access to a Mac; but theoretically it should be.
|
| import socket
| def my_ipaddr(interface_hostname=None):
| # give the hostname of the interface you want the ipaddr of
| hostname = interface_hostname or socket.gethostname()
| s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
| s.bind(hostname, 0)
| ipaddr, port = s.getsockname()
| s.close()
| return ipaddr # returns 'nnn.nnn.nnn.nnn' (StringType)
|
| You aren't connecting to anything so this _should_ work even if you are
| not on a network at the time (PPP), the interface just needs to be
| plumbed and initialized. The begged question would be: how do you get
| the hostnames of multiple interfaces from within Python. Anyone have a
| good answer for that?

I ran into this problem in a PPP situation, and I had to crank harder
than that. Of course multiple networks is part of the problem (I had
separate local and dial-up networks, both via PPP.) But for me, even
with only one network, in a dynamic situation like most PPP services,
I got a valid IP only when I attempt to connect to something via that
network. I more or less arbitrarily chose to connect to my primary
DNS service.

The recent thread on ifconfig interface is germane here. If the ifconfig
ioctls work on your platform (i.e., UNIX), you can retrieve all kinds
of information about network interfaces, but I don't know if it has any
answer for valid PPP latency worries as discussed above, and at present
it would require some no-portability-guarantees struct packing (see thread
for more.)

Donn Cave, University Computing Services, University of Washington
donn@u.washington.edu
What's a good way to get my IP from Python? [ In reply to ]
Charles G Waldman <cgw@fnal.gov> writes:

> How about this? I don't know if it's "really good" but it works,
> and it shows you how to do IOCTL's from Python. (Lately, folks on
> the list have been suggesting writing a new extension module
> whenever you need to do such a thing, but this is IMO unattractive
> from the point of view of easy redistribution of code).

I actually wrote a basic ifconfig module, although it's probably not
as thorough as it could be...

Personally, I find C more fun/easier to work with at this level.

Hopefully, I will be able to release my work soon, and then people can
vote with their feet. I have what I need, so I will make sure it
keeps working and doing what I want.

Ciao,
--
David N. Welton, Web Engineer, Linuxcare, Inc.
415.354.4878 x241 tel, 415.701.7457 fax
dwelton@linuxcare.com, http://www.linuxcare.com/
Linuxcare. At the center of Linux.
What's a good way to get my IP from Python? [ In reply to ]
Yes, it does work on a Mac.

Dan, Dan@Grassi.com

----------
In article <2EZr3.1342$EG4.232940@news.shore.net>, "Michael P. Reilly"
<arcege@shore.net> wrote:


> don't have
> access to a Mac; but theoretically it should be.
>
> import socket
> def my_ipaddr(interface_hostname=None):
> # give the hostname of the interface you want the ipaddr of
> hostname = interface_hostname or socket.gethostname()
> s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
> s.bind(hostname, 0)
> ipaddr, port = s.getsockname()
> s.close()
> return ipaddr # returns 'nnn.nnn.nnn.nnn' (StringType)