Freitag, 27. Juli 2007

IP-Adresse und Python

Vor einer Weile habe ich mich dem Suchen der IP-Adressen unter Python herumgeschlagen. Ich habe versucht die IP-Adresse des System zu finden, habe aber immer die Loopback-Adresse zurückerhalten. Obwohl es unter Windows fehlerfrei funktioniert hat.

import socket

# System name
sys_name = socket.gethostname()
# IP adress
ip_addr = socket.gethostbyname(sys_name)

print ip_addr 
Anscheinend muss man unter Linux auf /proc/net/arp zurückgreifen oder es über ifconfig machen. Ich habe es dann mal mit /proc/net/arp versucht.
cat /proc/net/arp
Liefert in meinem Fall
IP address       HW type     Flags       HW address            Mask     Device
192.168.1.100     0x1         0x2         00:0E:33:D5:3B:3B     *        ath0
In ein Python-Script verpackt, sieht es so aus.
import os

ip_adress = os.system('cat /proc/net/arp | grep eth0 | cut -c -15')
print ip_adress
Es funktioniert jedoch auch mit ifconfig nach dem gleichen Schema, wie oben. Ein bisschen mit Pipes arbeiten und schon geht es... Diese Version habe ich im Netz gefunden. Leider habe ich die Quellen-Angabe verbummelt. Aus meiner Sicht ist sie sehr elegant, auch wenn ich nicht alles verstehe, da meine Python-Kenntnisse immer noch beschränkt sind.
import socket
import fcntl
import struct

def get_ip_address(ifname):
s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
return socket.inet_ntoa(fcntl.ioctl(
   s.fileno(),
   0x8915,  # SIOCGIFADDR
   struct.pack('256s', ifname[:15])
)[20:24])

print get_ip_address('ath0')
Als Alternative würde Netstat eine schönere Übersicht liefern, wenn man es nur in der Konsole benutzt...

5 Kommentare:

Rudd-O hat gesagt…

Isn't it easier to do:

import commands
status,output = commands.getstatusoutput("ip addr")

then import re and use re.matchall() to grab the addresses?

This would also be portable.

Rudd-O hat gesagt…

For the record I'm Rudd-O, but I couldn't create a Google account with that name. Sorry for the mixup.

Unknown hat gesagt…

Das System hat keine IP adresse, ein netzwerkinterface hat eine IP adresse. Wenn ich mir deinen Python Code anschau, holt sich dieser die IP Adresse, die an deinen rechnernamen gebunden ist. D.h. wenn dein recher als `hostname´ localhost oder localhost.localdomain hat, dann ist die IP Adresse 127.0.0.1. Wenn dein hostname www.gmx.net ist, dann gibt diese funktion 217.72.204.254 zurück (zumindest hier in österreich).

Das mit dem ARP gibt dir die IP Adresse des eth0 interfaces. aber wenn man gerade mit rausb0 per WLAN im Netz ist?

die get_ip_address() funktion ruft eine ioctl() funktion, SIOCGIFADDR, fuer das als parameter uebergebene interface auf. Dazu macht es zuerst mal einen socket() call um einen filedeskripor in netzwerksubsystem des kernels zu erhalten, und ruft dann fcntl.ioctl() auf. Der 3. parameter ist eine struct, die mit hilfe des Python struct modules so erzeugt wird, dass sie C layout hat, und den interface namen als inhalt hat.

hth

Fabian hat gesagt…

Wenn der Hostnamen nicht localhost ist, dann funktioniert es mit socket nicht. Auf jeden Fall bei mir.

Es geht um das Grundsätzliche...in meinem Fall wird es wahrscheinlich immer eth0 sein (ansonsten liesse sich das sicher auch auf andere Interfaces ausbauen).


Danke für die Erklärungen, resp. die Kommentierungen meines gefundenen Skripts.

Fabian hat gesagt…

Das letzte Beispiel basiert auf Informationen aus dem Python Cookbook.