使用Python的stdlib查找本地IP地址

我如何在Python平台上独立地使用本地IP地址(即192.168.xx或10.0.xx)并仅使用标准库?

 import socket socket.gethostbyname(socket.gethostname()) 

这不会总是起作用的(在/etc/hosts名为127.0.0.1机器上返回127.0.0.1 ),那么gimel会显示什么,请使用socket.getfqdn() 。 当然你的机器需要一个可parsing的主机名。

我只是发现这个,但它似乎有点hackish,但他们说,试了一下*尼克斯,我做了窗口,它的工作。

 import socket s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) s.connect(("8.8.8.8", 80)) print(s.getsockname()[0]) s.close() 

这假设你有一个互联网接入,并没有本地代理。

作为一个名为myip的别名,它应该在任何地方工作:

 alias myip="python -c 'import socket; print([l for l in ([ip for ip in socket.gethostbyname_ex(socket.gethostname())[2] if not ip.startswith(\"127.\")][:1], [[(s.connect((\"8.8.8.8\", 53)), s.getsockname()[0], s.close()) for s in [socket.socket(socket.AF_INET, socket.SOCK_DGRAM)]][0][1]]) if l][0][0])'" 
  • 可以正确使用Python 2.x,Python 3.x,现代和旧版Linux发行版,OSX / macOS和Windows来查找当前的IPv4地址。
  • 对于具有多个IP地址,IPv6,没有configurationIP地址或无法访问Internet的机器,不会返回正确的结果。

同上,但只有Python代码:

 import socket print([l for l in ([ip for ip in socket.gethostbyname_ex(socket.gethostname())[2] if not ip.startswith("127.")][:1], [[(s.connect(('8.8.8.8', 53)), s.getsockname()[0], s.close()) for s in [socket.socket(socket.AF_INET, socket.SOCK_DGRAM)]][0][1]]) if l][0][0]) 
  • 如果没有configurationIP地址,这将引发exception。

没有互联网连接也可以在局域网上工作的版本:

 import socket print((([ip for ip in socket.gethostbyname_ex(socket.gethostname())[2] if not ip.startswith("127.")] or [[(s.connect(("8.8.8.8", 53)), s.getsockname()[0], s.close()) for s in [socket.socket(socket.AF_INET, socket.SOCK_DGRAM)]][0][1]]) + ["no IP found"])[0]) 

(感谢@ ccpizza )


背景

使用socket.gethostbyname(socket.gethostname())在这里不起作用,因为我所在的计算机有一个/etc/hosts其中有重复的条目和对自身的引用。 socket.gethostbyname()只返回/etc/hosts的最后一个条目。

这是我最初的尝试,它清除了以"127."开头的所有地址。 :

 import socket print([ip for ip in socket.gethostbyname_ex(socket.gethostname())[2] if not ip.startswith("127.")][:1]) 

这适用于Linux和Windows上的Python 2和3,但不涉及多个networking设备或IPv6。 然而,它停止了最近的Linux发行版,所以我尝试了这种替代技术。 它尝试通过端口53连接到8.8.8.8的Google DNS服务器:

 import socket print([(s.connect(('8.8.8.8', 53)), s.getsockname()[0], s.close()) for s in [socket.socket(socket.AF_INET, socket.SOCK_DGRAM)]][0][1]) 

然后,我将上述两种技术组合到应该在任何地方工作的myip ,并在此答案的顶部创buildmyip别名和Python片段。

随着IPv6的日益stream行,以及具有多个networking接口的服务器,使用第三方Python模块来查找IP地址可能比此处列出的任何技术都更加健壮和可靠。

您可以使用netifaces模块。 只需input:

 pip install netifaces 

在您的命令shell中,它将自行安装在默认的Python安装中。

那么你可以像这样使用它:

 from netifaces import interfaces, ifaddresses, AF_INET for ifaceName in interfaces(): addresses = [i['addr'] for i in ifaddresses(ifaceName).setdefault(AF_INET, [{'addr':'No IP addr'}] )] print '%s: %s' % (ifaceName, ', '.join(addresses)) 

在我的电脑上打印:

  {45639BDC-1050-46E0-9BE9-075C30DE1FBC}:192.168.0.100
 {D43A468B-F3AE-4BF9-9391-4863A4500583}:10.5.9.207 

这个模块的作者声称它应该在Windows,UNIX和Mac OS X上工作。

这个函数返回本地盒子(具有默认路由的那个)上的“主”IP

  • 不需要可路由的networking访问或任何连接。
  • 即使从networking上拔下所有接口,也能正常工作。
  • 不需要甚至试图去其他任何地方
  • 适用于NAT,公共,私人,外部和内部IP
  • 纯Python 2没有外部依赖。
  • 适用于Linux,Windows和OSX。

Python 2或3:

 import socket def get_ip(): s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) try: # doesn't even have to be reachable s.connect(('10.255.255.255', 1)) IP = s.getsockname()[0] except: IP = '127.0.0.1' finally: s.close() return IP 

这将返回一个主要的IP(一个默认路由)。 如果你需要所有IP连接到所有的接口(包括本地主机等),看到这个答案 。

如果你在家里的NAT箱子后面,就不会显示你的公网NAT,而是在你的本地WIFI路由器上有默认路由的本地networking上的私有NAT IP; 得到你的无线路由器的外部IP将需要运行这个盒子,或连接到一个外部服务,如whatismyip.com/whatismyipaddress.com,可以反映IP …但这是完全不同的原来的问题。 🙂

根据Pedro的build议,在评论中更新connect()调用。 (如果您需要一个特定的许可证声明,这是任何使用的公共领域/免费,或者您可以select每个堆栈溢出的代码/内容许可证的MIT / CC2-BY-SA。

套接字API方法

 import socket # from http://commandline.org.uk/python/how-to-find-out-ip-address-in-python/ def getNetworkIp(): s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) s.connect(('INSERT SOME TARGET WEBSITE.com', 0)) return s.getsockname()[0] 

缺点:

  • 不是跨平台的。
  • 需要更多的回退代码,绑定到互联网上的特定地址的存在
  • 如果你在NAT后面,这也不起作用
  • 可能会创build一个UDP连接,而不是独立于(通常是ISP的)DNS可用性(请参阅其他答案,例如使用8.8.8.8:Google(偶然也是DNS)服务器)
  • 非常差的forms来引入代码中的第三方依赖(如google.com )作为指定networking接口的方式,除非您特别需要接口的公共IP,它将路由到您想要的特定网站。 垃圾无辜的第三方是不好的。 坏。 坏。

reflection器方法

(请注意,这并不回答OP的本地IP地址的问题,例如192.168 …;它给你你的公共IP地址,根据使用情况,这可能更合乎需要)。

你可以查询一些像whatismyip.com这样的网站(但用一个API),比如:

 from urllib.request import urlopen import re def getPublicIp(): data = str(urlopen('http://checkip.dyndns.com/').read()) # data = '<html><head><title>Current IP Check</title></head><body>Current IP Address: 65.96.168.198</body></html>\r\n' return re.compile(r'Address: (\d+\.\d+\.\d+\.\d+)').search(data).group(1) 

或者如果使用python2:

 from urllib import urlopen import re def getPublicIp(): data = str(urlopen('http://checkip.dyndns.com/').read()) # data = '<html><head><title>Current IP Check</title></head><body>Current IP Address: 65.96.168.198</body></html>\r\n' return re.compile(r'Address: (\d+\.\d+\.\d+\.\d+)').search(data).group(1) 

优点:

  • 这种方法的一个优点是它是跨平台的
  • 它从丑陋的NAT(例如你的家庭路由器)后面工作。

缺点(和解决方法):

  • 要求这个网站起来,格式不变(几乎肯定不会),你的DNS服务器正在工作。 可以通过查询其他第三方IP地址reflection器来解决这个问题。
  • 如果你没有查询多个reflection器(为了防止受到攻击的reflection器告诉你,你的地址是不是的东西),或者如果你不使用HTTPS(防止中间人攻击假装成为服务器)

编辑 :虽然最初我以为这些方法真的很糟糕(除非你使用了很多的回退,这些代码可能在很多年后都是不相关的),但这确实提出了“互联网是什么”的问题。 计算机可能有许多接口指向许多不同的networking。 有关该主题的更全面描述,请访问Google gateways and routes 。 计算机可能能够通过内部网关访问内部networking,或者通过例如路由器(通常情况下)的网关访问全球networking。 OP请求的本地IP地址只针对单个链路层定义好,因此您必须指定(“是网卡还是以太网电缆,我们正在谈论的是什么?”) 。 这个问题可能有多个非唯一的答案。 但是,全球networking上的全球IP地址可能是明确的(在没有大规模networking碎片的情况下):可能是通过可以访问TLD的网关的返回path。

如果计算机具有到Internet的路由,则即使/ etc / hosts设置不正确,也始终会获得首选的本地IP地址。

 import socket s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) s.connect(('8.8.8.8', 1)) # connect() for UDP doesn't send packets local_ip_address = s.getsockname()[0] 

在Linux上:

 >>> import socket, struct, fcntl >>> sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) >>> sockfd = sock.fileno() >>> SIOCGIFADDR = 0x8915 >>> >>> def get_ip(iface = 'eth0'): ... ifreq = struct.pack('16sH14s', iface, socket.AF_INET, '\x00'*14) ... try: ... res = fcntl.ioctl(sockfd, SIOCGIFADDR, ifreq) ... except: ... return None ... ip = struct.unpack('16sH2x4s8x', res)[2] ... return socket.inet_ntoa(ip) ... >>> get_ip('eth0') '10.80.40.234' >>> 

我在我的ubuntu机器上使用这个:

 import commands commands.getoutput("/sbin/ifconfig").split("\n")[1].split()[1][5:] 

即时通讯使用以下模块

 #!/usr/bin/python # module for getting the lan ip address of the computer import os import socket if os.name != "nt": import fcntl import struct def get_interface_ip(ifname): s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) return socket.inet_ntoa(fcntl.ioctl( s.fileno(), 0x8915, # SIOCGIFADDR struct.pack('256s', bytes(ifname[:15], 'utf-8')) # Python 2.7: remove the second argument for the bytes call )[20:24]) def get_lan_ip(): ip = socket.gethostbyname(socket.gethostname()) if ip.startswith("127.") and os.name != "nt": interfaces = ["eth0","eth1","eth2","wlan0","wlan1","wifi0","ath0","ath1","ppp0"] for ifname in interfaces: try: ip = get_interface_ip(ifname) break; except IOError: pass return ip 

经过Windows和Linux的testing(并且不需要额外的模块),用于基于IPv4的局域网中的系统。

接口名称的固定列表不适用于最近的linux版本,它们采用了由Alexander指出的有关可预测的接口名称的systemd v197更改。 在这种情况下,您需要手动将该列表replace为系统上的接口名称,或者使用其他解决scheme(如netifaces) 。

如果您不想使用外部软件包而不想依赖外部Internet服务器,这可能会有所帮助。 这是我在Google代码search中find的代码示例,并进行了修改以返回所需的信息:

 def getIPAddresses(): from ctypes import Structure, windll, sizeof from ctypes import POINTER, byref from ctypes import c_ulong, c_uint, c_ubyte, c_char MAX_ADAPTER_DESCRIPTION_LENGTH = 128 MAX_ADAPTER_NAME_LENGTH = 256 MAX_ADAPTER_ADDRESS_LENGTH = 8 class IP_ADDR_STRING(Structure): pass LP_IP_ADDR_STRING = POINTER(IP_ADDR_STRING) IP_ADDR_STRING._fields_ = [ ("next", LP_IP_ADDR_STRING), ("ipAddress", c_char * 16), ("ipMask", c_char * 16), ("context", c_ulong)] class IP_ADAPTER_INFO (Structure): pass LP_IP_ADAPTER_INFO = POINTER(IP_ADAPTER_INFO) IP_ADAPTER_INFO._fields_ = [ ("next", LP_IP_ADAPTER_INFO), ("comboIndex", c_ulong), ("adapterName", c_char * (MAX_ADAPTER_NAME_LENGTH + 4)), ("description", c_char * (MAX_ADAPTER_DESCRIPTION_LENGTH + 4)), ("addressLength", c_uint), ("address", c_ubyte * MAX_ADAPTER_ADDRESS_LENGTH), ("index", c_ulong), ("type", c_uint), ("dhcpEnabled", c_uint), ("currentIpAddress", LP_IP_ADDR_STRING), ("ipAddressList", IP_ADDR_STRING), ("gatewayList", IP_ADDR_STRING), ("dhcpServer", IP_ADDR_STRING), ("haveWins", c_uint), ("primaryWinsServer", IP_ADDR_STRING), ("secondaryWinsServer", IP_ADDR_STRING), ("leaseObtained", c_ulong), ("leaseExpires", c_ulong)] GetAdaptersInfo = windll.iphlpapi.GetAdaptersInfo GetAdaptersInfo.restype = c_ulong GetAdaptersInfo.argtypes = [LP_IP_ADAPTER_INFO, POINTER(c_ulong)] adapterList = (IP_ADAPTER_INFO * 10)() buflen = c_ulong(sizeof(adapterList)) rc = GetAdaptersInfo(byref(adapterList[0]), byref(buflen)) if rc == 0: for a in adapterList: adNode = a.ipAddressList while True: ipAddr = adNode.ipAddress if ipAddr: yield ipAddr adNode = adNode.next if not adNode: break 

用法:

 >>> for addr in getIPAddresses(): >>> print addr 192.168.0.100 10.5.9.207 

因为它依赖于windll ,所以只能在Windows上使用。

在Debian(testing),我怀疑大多数Linux的..

 import commands RetMyIP = commands.getoutput("hostname -I") 

在MS Windows上(testing)

 import socket socket.gethostbyname(socket.gethostname()) 

我不认为这个版本已经发布了。 我在Ubuntu 12.04上testing了python 2.7。

find这个解决scheme: http : //code.activestate.com/recipes/439094-get-the-ip-address-associated-with-a-network-inter/

 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]) 

示例结果:

get_ip_address('eth0')'38 .113.228.130'

通过命令行实用程序生成“干净”输出的一种简单方法:

 import commands ips = commands.getoutput("/sbin/ifconfig | grep -i \"inet\" | grep -iv \"inet6\" | " + "awk {'print $2'} | sed -ne 's/addr\:/ /p'") print ips 

它将显示系统上的所有IPv4地址。

仅供参考我可以validation方法:

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

适用于OS X(10.6,10.5),Windows XP和pipe理良好的RHEL部门服务器。 它不是在一个非常小的CentOS虚拟机上工作,我只是做一些内核黑客攻击。 所以对于这个例子,你可以检查一个127.0.0.1地址,在这种情况下,请执行以下操作:

 if addr == "127.0.0.1": import commands output = commands.getoutput("/sbin/ifconfig") addr = parseaddress(output) 

然后从输出parsingIP地址。 应该注意的是,ifconfig默认情况下不在正常用户的PATH中,这就是为什么我在命令中给出完整path的原因。 我希望这有帮助。

恐怕没有任何好的平台独立的方法来做到这一点,除了连接到另一台计算机,并发送给你你的IP地址。 例如: findmyipaddress 。 请注意,如果您需要NAT后面的IP地址,那么这将不起作用,除非您连接的计算机也位于NAT之后。

这里有一个解决scheme可以在Linux中使用: 获取与networking接口关联的IP地址 。

这将在大多数Linux盒子上工作:

 import socket, subprocess, re def get_ipv4_address(): """ Returns IP address(es) of current machine. :return: """ p = subprocess.Popen(["ifconfig"], stdout=subprocess.PIPE) ifc_resp = p.communicate() patt = re.compile(r'inet\s*\w*\S*:\s*(\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3})') resp = patt.findall(ifc_resp[0]) print resp get_ipv4_address() 
 import socket [i[4][0] for i in socket.getaddrinfo(socket.gethostname(), None)] 

这是UnkwnTech答案的变种 – 它提供了一个get_local_addr()函数,它返回主机的主局域网ip地址。 我发布它,因为这增加了一些东西:ipv6的支持,error handling,忽略本地主机/ linklocal地址,并使用TESTNET地址(rfc5737)连接到。

 # imports import errno import socket # localhost prefixes _local_networks = ("127.", "0:0:0:0:0:0:0:1") # ignore these prefixes -- localhost, unspecified, and link-local _ignored_networks = _local_networks + ("0.", "0:0:0:0:0:0:0:0", "169.254.", "fe80:") def detect_family(addr): if "." in addr: assert ":" not in addr return socket.AF_INET elif ":" in addr: return socket.AF_INET6 else: raise ValueError("invalid ipv4/6 address: %r" % addr) def expand_addr(addr): """convert address into canonical expanded form -- no leading zeroes in groups, and for ipv6: lowercase hex, no collapsed groups. """ family = detect_family(addr) addr = socket.inet_ntop(family, socket.inet_pton(family, addr)) if "::" in addr: count = 8-addr.count(":") addr = addr.replace("::", (":0" * count) + ":") if addr.startswith(":"): addr = "0" + addr return addr def _get_local_addr(family, remote): try: s = socket.socket(family, socket.SOCK_DGRAM) try: s.connect((remote, 9)) return s.getsockname()[0] finally: s.close() except socket.error: return None def get_local_addr(remote=None, ipv6=True): """get LAN address of host :param remote: return LAN address that host would use to access that specific remote address. by default, returns address it would use to access the public internet. :param ipv6: by default, attempts to find an ipv6 address first. if set to False, only checks ipv4. :returns: primary LAN address for host, or ``None`` if couldn't be determined. """ if remote: family = detect_family(remote) local = _get_local_addr(family, remote) if not local: return None if family == socket.AF_INET6: # expand zero groups so the startswith() test works. local = expand_addr(local) if local.startswith(_local_networks): # border case where remote addr belongs to host return local else: # NOTE: the two addresses used here are TESTNET addresses, # which should never exist in the real world. if ipv6: local = _get_local_addr(socket.AF_INET6, "2001:db8::1234") # expand zero groups so the startswith() test works. if local: local = expand_addr(local) else: local = None if not local: local = _get_local_addr(socket.AF_INET, "192.0.2.123") if not local: return None if local.startswith(_ignored_networks): return None return local 

ninjagecko的答案的变化。 这应该在允许UDP广播的任何LAN上工作,并且不需要访问局域网或互联网上的地址。

 import socket def getNetworkIp(): s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) s.setsockopt(socket.SOL_SOCKET, socket.SO_BROADCAST, 1) s.connect(('<broadcast>', 0)) return s.getsockname()[0] print (getNetworkIp()) 

127.0.1.1 你的真实IP地址。 更一般地说,一台电脑可以有任意数量的IP地址。 您可以将它们过滤为专用networking – 127.0.0.0/8,10.0.0.0/8,172.16.0.0/12和192.168.0.0/16。

但是,没有跨平台的方式来获取所有的IP地址。 在Linux上,您可以使用SIOCGIFCONF ioctl。

使用IP命令的命令版本略有改进,并返回IPv4和IPv6地址:

 import commands,re,socket #A generator that returns stripped lines of output from "ip address show" iplines=(line.strip() for line in commands.getoutput("ip address show").split('\n')) #Turn that into a list of IPv4 and IPv6 address/mask strings addresses1=reduce(lambda a,v:a+v,(re.findall(r"inet ([\d.]+/\d+)",line)+re.findall(r"inet6 ([\:\da-f]+/\d+)",line) for line in iplines)) #addresses1 now looks like ['127.0.0.1/8', '::1/128', '10.160.114.60/23', 'fe80::1031:3fff:fe00:6dce/64'] #Get a list of IPv4 addresses as (IPstring,subnetsize) tuples ipv4s=[(ip,int(subnet)) for ip,subnet in (addr.split('/') for addr in addresses1 if '.' in addr)] #ipv4s now looks like [('127.0.0.1', 8), ('10.160.114.60', 23)] #Get IPv6 addresses ipv6s=[(ip,int(subnet)) for ip,subnet in (addr.split('/') for addr in addresses1 if ':' in addr)] 

This answer is my personal attempt to solve the problem of getting the LAN IP, since socket.gethostbyname(socket.gethostname()) also returned 127.0.0.1. This method does not require Internet just a LAN connection. Code is for Python 3.x but could easily be converted for 2.x. Using UDP Broadcast:

 import select import socket import threading from queue import Queue, Empty def get_local_ip(): def udp_listening_server(): s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) s.bind(('<broadcast>', 8888)) s.setblocking(0) while True: result = select.select([s],[],[]) msg, address = result[0][0].recvfrom(1024) msg = str(msg, 'UTF-8') if msg == 'What is my LAN IP address?': break queue.put(address) queue = Queue() thread = threading.Thread(target=udp_listening_server) thread.queue = queue thread.start() s2 = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) s2.setsockopt(socket.SOL_SOCKET, socket.SO_BROADCAST, 1) waiting = True while waiting: s2.sendto(bytes('What is my LAN IP address?', 'UTF-8'), ('<broadcast>', 8888)) try: address = queue.get(False) except Empty: pass else: waiting = False return address[0] if __name__ == '__main__': print(get_local_ip()) 

Well you can use the command "ip route" on GNU/Linux to know your current IP address.

This shows the IP given to the interface by the DHCP server running on the router/modem. Usually "192.168.1.1/24" is the IP for local network where "24" means the range of posible IP addresses given by the DHCP server within the mask range.

Here's an example: Note that PyNotify is just an addition to get my point straight and is not required at all

 #! /usr/bin/env python import sys , pynotify if sys.version_info[1] != 7: raise RuntimeError('Python 2.7 And Above Only') from subprocess import check_output # Available on Python 2.7+ | N/A IP = check_output(['ip', 'route']) Split_Result = IP.split() # print Split_Result[2] # Remove "#" to enable pynotify.init("image") notify = pynotify.Notification("Ip", "Server Running At:" + Split_Result[2] , "/home/User/wireless.png") notify.show() 

The advantage of this is that you don't need to specify the network interface. That's pretty useful when running a socket server

You can install PyNotify using easy_install or even Pip:

 easy_install py-notify 

要么

 pip install py-notify 

or within python script/interpreter

 from pip import main main(['install', 'py-notify']) 

netifaces is available via pip and easy_install. (I know, it's not in base, but it could be worth the install.)

netifaces does have some oddities across platforms:

  • The localhost/loop-back interface may not always be included (Cygwin).
  • Addresses are listed per-protocol (eg, IPv4, IPv6) and protocols are listed per-interface. On some systems (Linux) each protocol-interface pair has its own associated interface (using the interface_name:n notation) while on other systems (Windows) a single interface will have a list of addresses for each protocol. In both cases there is a protocol list, but it may contain only a single element.

Here's some netifaces code to play with:

 import netifaces PROTO = netifaces.AF_INET # We want only IPv4, for now at least # Get list of network interfaces # Note: Can't filter for 'lo' here because Windows lacks it. ifaces = netifaces.interfaces() # Get all addresses (of all kinds) for each interface if_addrs = [netifaces.ifaddresses(iface) for iface in ifaces] # Filter for the desired address type if_inet_addrs = [addr[PROTO] for addr in if_addrs if PROTO in addr] iface_addrs = [s['addr'] for a in if_inet_addrs for s in a if 'addr' in s] # Can filter for '127.0.0.1' here. 

The above code doesn't map an address back to its interface name (useful for generating ebtables/iptables rules on the fly). So here's a version that keeps the above information with the interface name in a tuple:

 import netifaces PROTO = netifaces.AF_INET # We want only IPv4, for now at least # Get list of network interfaces ifaces = netifaces.interfaces() # Get addresses for each interface if_addrs = [(netifaces.ifaddresses(iface), iface) for iface in ifaces] # Filter for only IPv4 addresses if_inet_addrs = [(tup[0][PROTO], tup[1]) for tup in if_addrs if PROTO in tup[0]] iface_addrs = [(s['addr'], tup[1]) for tup in if_inet_addrs for s in tup[0] if 'addr' in s] 

And, no, I'm not in love with list comprehensions. It's just the way my brain works these days.

The following snippet will print it all out:

 from __future__ import print_function # For 2.x folks from pprint import pprint as pp print('\nifaces = ', end='') pp(ifaces) print('\nif_addrs = ', end='') pp(if_addrs) print('\nif_inet_addrs = ', end='') pp(if_inet_addrs) print('\niface_addrs = ', end='') pp(iface_addrs) 

请享用!

To get the ip address you can use a shell command directly in python :

 import socket, subprocess def getIpAndHostname(): hostname = socket.gethostname() shell_cmd = "ifconfig | awk '/inet addr/{print substr($2,6)}'" proc = subprocess.Popen([shell_cmd], stdout=subprocess.PIPE, shell=True) (out, err) = proc.communicate() ip_list = out.split('\n') ip = ip_list[0] for _ip in ip_list: try: if _ip != "127.0.0.1" and _ip.split(".")[3] != "1": ip = _ip except: pass return ip, hostname ip_addr, hostname = getIpAndHostname() 

I had to solve the problem "Figure out if an IP address is local or not", and my first thought was to build a list of IPs that were local and then match against it. This is what led me to this question. However, I later realized there is a more straightfoward way to do it: Try to bind on that IP and see if it works.

 _local_ip_cache = [] _nonlocal_ip_cache = [] def ip_islocal(ip): if ip in _local_ip_cache: return True if ip in _nonlocal_ip_cache: return False s = socket.socket() try: try: s.bind((ip, 0)) except socket.error, e: if e.args[0] == errno.EADDRNOTAVAIL: _nonlocal_ip_cache.append(ip) return False else: raise finally: s.close() _local_ip_cache.append(ip) return True 

I know this doesn't answer the question directly, but this should be helpful to anyone trying to solve the related question and who was following the same train of thought. This has the advantage of being a cross-platform solution (I think).

 import socket socket.gethostbyname(socket.getfqdn()) 

Note: This is not using the standard library, but quite simple.

$ pip install pif

 from pif import get_public_ip get_public_ip() 

For a list of IP addresses on *nix systems,

 import subprocess co = subprocess.Popen(['ifconfig'], stdout = subprocess.PIPE) ifconfig = co.stdout.read() ip_regex = re.compile('((25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-4]|2[0-5][0-9]|[01]?[0-9][0-9]?))') [match[0] for match in ip_regex.findall(ifconfig, re.MULTILINE)] 

Though it's a bit late for this answer, I thought someone else may find it useful 🙂

PS : It'll return Broadcast addresses and Netmask as well.