如何找到本地IP地址(即192.168.x。x或10.0.x.x)在Python平台独立,只使用标准库?


当前回答

在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'
>>> 

其他回答

在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'
>>> 

Windows解决方案,要么接受,要么放弃。

在当前活动的无线局域网[无线局域网]上,即计算机的ip地址(wifi路由器或网络交换机)。

注意:它不是设备的公共IP,不涉及任何外部请求、包和公共api。

核心思想是解析shell命令:ipconfig或linux上的ifconfig的输出。我们使用子进程来获取输出。

def wlan_ip():
    import subprocess
    result=subprocess.run('ipconfig',stdout=subprocess.PIPE,text=True).stdout.lower()
    scan=0
    for i in result.split('\n'):
        if 'wireless' in i: #use "wireless" or wireless adapters and "ethernet" for wired connections
            scan=1
        if scan:
            if 'ipv4' in i:
                return i.split(':')[1].strip()
print(wlan_ip())

这是在CMD:'ipconfig'后发生的事情:

我们得到这个输出,我们在python中使用subprocess output捕获它。

C:\Users\戴尔> ipconfig

Wireless LAN adapter Wi-Fi:

   Connection-specific DNS Suffix  . :
   Link-local IPv6 Address . . . . . : fe80::f485:4a6a:e7d5:1b1c%4
   IPv4 Address. . . . . . . . . . . : 192.168.0.131
   Subnet Mask . . . . . . . . . . . : 255.255.255.0
   Default Gateway . . . . . . . . . : 192.168.0.1

我们用python语言解析了字符串,以选择当前网络上无线适配器的IP的方式。

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

你可以使用netifaces模块。类型:

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上工作。

这不是很Pythonic,但它在Windows上可靠地工作。

def getWinIP(version = 'IPv4'):
    import subprocess
    if version not in ['IPv4', 'IPv6']:
        print 'error - protocol version must be "IPv4" or "IPv6"'
        return None
    ipconfig = subprocess.check_output('ipconfig')
    my_ip = []
    for line in ipconfig.split('\n'):
        if 'Address' in line and version in line:
            my_ip.append(line.split(' : ')[1].strip())
    return my_ip

print getWinIP()

是的,这是一种黑客行为,但有时我不想事后怀疑操作系统,直接使用内置的和有效的操作系统就行了。