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

时间:2022-08-22 13:16:44

How can I find local IP addresses (i.e. 192.168.x.x or 10.0.x.x) in Python platform independently and using only the standard library?

如何找到本地IP地址(即192.168.x)。在Python平台中,仅使用标准库?

41 个解决方案

#1


312  

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

This won't work always (returns 127.0.0.1 on machines having the hostname in /etc/hosts as 127.0.0.1), a paliative would be what gimel shows, use socket.getfqdn() instead. Of course your machine needs a resolvable hostname.

这并不总是有效的(在/etc/主机上拥有主机名的机器上的返回127.0.0.1作为127.0.0.1),paliative将是gimel所展示的,使用socket.getfqdn()代替。当然,您的机器需要一个可解析的主机名。

#2


315  

I just found this but it seems a bit hackish, however they say tried it on *nix and I did on windows and it worked.

我刚发现了这个,但是看起来有点乱,不过他们说在*nix上试过了,我在windows上做了,而且成功了。

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

This assumes you have an internet access, and that there is no local proxy.

这假设您有一个internet访问,并且没有本地代理。

#3


125  

As an alias called myip, that should work everywhere:

作为一个别名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])'"
  • Works correctly with Python 2.x, Python 3.x, modern and old Linux distros, OSX/macOS and Windows for finding the current IPv4 address.
  • 正确使用Python 2。x,Python 3。x,现代和旧的Linux发行版,OSX/macOS和Windows寻找当前的IPv4地址。
  • Will not return the correct result for machines with multiple IP addresses, IPv6, no configured IP address or no internet access.
  • 对于具有多个IP地址、IPv6、没有配置IP地址或没有internet访问的机器,将不会返回正确的结果。

Same as above, but only the Python code:

和上面一样,但只有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])
  • This will throw an exception if no IP address is configured.
  • 如果没有配置IP地址,这将引发异常。

Version that will also work on LANs without an internet connection:

该版本也将在没有互联网连接的局域网中工作:

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

(thanks @ccpizza)

(感谢@ccpizza)


Background:

背景:

Using socket.gethostbyname(socket.gethostname()) did not work here, because one of the computers I was on had an /etc/hosts with duplicate entries and references to itself. socket.gethostbyname() only returns the last entry in /etc/hosts.

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

This was my initial attempt, which weeds out all addresses starting with "127.":

这是我最初的尝试,从“127”开始清除所有的地址。

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

This works with Python 2 and 3, on Linux and Windows, but does not deal with several network devices or IPv6. However, it stopped working on recent Linux distros, so I tried this alternative technique instead. It tries to connect to the Google DNS server at 8.8.8.8 at port 53:

这适用于Python 2和3,在Linux和Windows上,但不处理多个网络设备或IPv6。但是,它停止了最近的Linux发行版,所以我尝试了这种替代技术。它尝试连接到端口53的谷歌DNS服务器,在8.8.8.8:

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

Then I combined the two above techniques into a one-liner that should work everywhere, and created the myip alias and Python snippet at the top of this answer.

然后,我将上述两种技术组合成一行程序,在每个地方都可以工作,并在这个答案的顶部创建了myip别名和Python代码段。

With the increasing popularity of IPv6, and for servers with multiple network interfaces, using a third-party Python module for finding the IP address is probably both more robust and reliable than any of the techiques listed here.

随着IPv6越来越受欢迎,对于具有多个网络接口的服务器,使用第三方Python模块来查找IP地址可能比这里列出的任何技术都更加健壮和可靠。

#4


78  

You can use the netifaces module. Just type:

你可以使用这个网友模块。类型:

pip install netifaces

in your command shell and it will install itself on default Python installation.

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

Then you can use it like this:

然后你可以这样使用:

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

On my computer it printed:

我的电脑上印着:

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

Author of this module claims it should work on Windows, UNIX and Mac OS X.

该模块的作者声称它应该在Windows、UNIX和Mac OS X上运行。

#5


73  

This function returns the "primary" IP on the local box (the one with a default route).

此函数将返回本地框上的“主”IP(具有默认路由的)。

  • Does NOT need routable net access or any connection at all.
  • 不需要可路由的网络访问或任何连接。
  • Works even if all interfaces are unplugged from the network.
  • 即使所有的接口都从网络断开,也可以工作。
  • Does NOT need or even try to get anywhere else.
  • 不需要甚至尝试去其他地方。
  • Works with NAT, public, private, external, and internal IP's
  • 与NAT,公共,私有,外部,和内部IP的工作。
  • Pure Python 2 with no external dependencies.
  • 纯Python 2,没有外部依赖项。
  • Works on Linux, Windows, and OSX.
  • 在Linux、Windows和OSX上工作。

Python 2 or 3:

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

This returns a single IP which is the primary (the one with a default route). If you need instead all IP's attached to all interfaces (including localhost, etc), see this answer.

这将返回一个单独的IP,该IP是主服务器(具有默认路由的IP)。如果您需要所有的IP连接到所有的接口(包括本地主机等),请参见这个答案。

If you are behind a NAT firewall like your wifi box at home, then this will not show your public NAT IP, but instead your private NAT IP on the local network which has a default route to your local WIFI router; getting your wifi router's external IP would either require running this on THAT box, or connecting to an external service such as whatismyip.com/whatismyipaddress.com that could reflect back the IP... but that is completely different from the original question. :)

如果你在一个NAT防火墙后,比如你家里的wifi,那么这将不会显示你的公共NAT IP,而是你的私有NAT IP在本地网络上,它有一个默认路由到你本地的wifi路由器;获取你的wifi路由器的外部IP要么需要在那个盒子上运行这个,要么连接到一个外部服务,比如whatismyip.com/whatismyipaddress.com,它可以反射IP…但这与最初的问题完全不同。:)

Updated connect() call per Pedro's suggestion in comments. (If you need a specific license statement, this is public domain/free for any use, or MIT/CC2-BY-SA per Stack Overflow's code/content license at your option.)

在评论中更新connect()调用per Pedro的建议。(如果你需要一个特定的许可声明,这是一个公共域/免费的任何使用,或者麻省理工/CC2-BY-SA每个Stack Overflow的代码/内容许可你的选择。)

#6


47  

Socket API method

套接字API方法

see https://*.com/a/28950776/711085

参见https://*.com/a/28950776/711085

Downsides:

缺点:

  • Not cross-platform.
  • 不是跨平台。
  • Requires more fallback code, tied to existence of particular addresses on the internet
  • 需要更多的后备代码,与互联网上特定地址的存在联系在一起。
  • This will also not work if you're behind a NAT
  • 如果你在NAT后面,这也不会起作用。
  • Probably creates a UDP connection, not independent of (usually ISP's) DNS availability (see other answers for ideas like using 8.8.8.8: Google's (coincidentally also DNS) server)
  • 可能会创建一个UDP连接,而不是独立于(通常是ISP的)DNS可用性(见其他的答案,比如使用8.8.8.8:谷歌的(碰巧也是DNS)服务器)
  • Make sure you make the destination address UNREACHABLE, like a numeric IP address that is spec-guaranteed to be unused. Do NOT use some domain like fakesubdomain.google.com or somefakewebsite.com; you'll still be spamming that party (now or in the future), and spamming your own network boxes as well in the process.
  • 确保您的目标地址是不可访问的,就像一个指定的数字IP地址,保证不被使用。不要使用一些域名,比如fakesubdomain.google.com或somefakewebsite.com;你仍然会在那个聚会(现在或将来)发送垃圾邮件,并且在这个过程中发送你自己的网络邮箱。

Reflector method

反射器方法

(Do note that this does not answer the OP's question of the local IP address, e.g. 192.168...; it gives you your public IP address, which might be more desirable depending on use case.)

(请注意,这并不能回答OP对本地IP地址的问题,例如192.168…;它提供了您的公共IP地址,根据用例,这可能更可取。

You can query some site like whatismyip.com (but with an API), such as:

您可以查询一些站点,如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)

or if using python2:

或者使用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)

Advantages:

优点:

  • One upside of this method is it's cross-platform
  • 这种方法的一个优点是它是跨平台的。
  • It works from behind ugly NATs (e.g. your home router).
  • 它在丑陋的NATs(比如你的家庭路由器)后面工作。

Disadvantages (and workarounds):

缺点(解决方案):

  • Requires this website to be up, the format to not change (almost certainly won't), and your DNS servers to be working. One can mitigate this issue by also querying other third-party IP address reflectors in case of failure.
  • 需要这个网站的启动,格式不改变(几乎肯定不会),和你的DNS服务器工作。如果出现故障,可以通过查询其他第三方IP地址反射器来缓解这个问题。
  • Possible attack vector if you don't query multiple reflectors (to prevent a compromised reflector from telling you that your address is something it's not), or if you don't use HTTPS (to prevent a man-in-the-middle attack pretending to be the server)
  • 如果您不查询多个反射器(防止反射器告诉您您的地址是某件事),或者您不使用HTTPS(为了防止中间人攻击假装是服务器),那么可能的攻击向量就会发生。

edit: Though initially I thought these methods were really bad (unless you use many fallbacks, the code may be irrelevant many years from now), it does pose the question "what is the internet?". A computer may have many interfaces pointing to many different networks. For a more thorough description of the topic, google for gateways and routes. A computer may be able to access an internal network via an internal gateway, or access the world-wide web via a gateway on for example a router (usually the case). The local IP address that the OP asks about is only well-defined with respect to a single link layer, so you have to specify that ("is it the network card, or the ethernet cable, which we're talking about?"). There may be multiple non-unique answers to this question as posed. However the global IP address on the world-wide web is probably well-defined (in the absence of massive network fragmentation): probably the return path via the gateway which can access the TLDs.

编辑:虽然一开始我认为这些方法很糟糕(除非你使用了很多的退路,但这些代码可能在很多年以后都是不相关的),它确实提出了一个问题:“什么是互联网?”计算机可能有许多接口指向许多不同的网络。为了更详细地描述这个主题,谷歌为网关和路由。计算机可以通过内部网关访问内部网络,或者通过网关(例如路由器)访问全球网络(通常是这样)。OP所要求的本地IP地址仅对单个链路层进行了定义,所以您必须指定(“是网卡还是以太网线,我们正在讨论的?”)。对于这个问题,可能有多个非唯一的答案。然而,全球网络上的全球IP地址可能是明确定义的(在没有大规模网络碎片的情况下):可能通过网关的返回路径可以访问TLDs。

#7


39  

If the computer has a route to the Internet, this will always work to get the preferred local ip address, even if /etc/hosts is not set correctly.

如果计算机有通向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]

#8


37  

On Linux:

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

#9


26  

im using following module:

我使用以下模块:

#!/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

Tested with windows and linux (and doesnt require additional modules for those) intended for use on systems which are in a single IPv4 based LAN.

使用windows和linux测试(并且不需要额外的模块),用于在一个基于IPv4的局域网中使用的系统。

The fixed list of interface names does not work for recent linux versions, which have adopted the systemd v197 change regarding predictable interface names as pointed out by Alexander. In such cases, you need to manually replace the list with the interface names on your system, or use another solution like netifaces.

接口名称的固定列表不适用于最近的linux版本,该版本采用了由Alexander指出的可预测接口名称的systemd v197更改。在这种情况下,您需要手动地将该列表替换为系统上的接口名称,或者使用其他的解决方案,如网络用户。

#10


25  

I use this on my ubuntu machines:

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

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

This doesn't work.

这并不工作。

#11


20  

If you don't want to use external packages and don't want to rely on outside Internet servers, this might help. It's a code sample that I found on Google Code Search and modified to return required information:

如果您不想使用外部包,并且不想依赖于外部Internet服务器,这可能会有所帮助。这是我在谷歌代码搜索和修改后发现的代码样本,以返回所需的信息:

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

Usage:

用法:

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

As it relies on windll, this will work only on Windows.

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

#12


14  

On Debian (tested) and I suspect most Linux's..

在Debian(测试)上,我怀疑大多数Linux。

import commands

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

On MS Windows (tested)

在MS Windows(测试)

import socket

socket.gethostbyname(socket.gethostname())

#13


11  

A version I do not believe that has been posted yet. I tested with python 2.7 on Ubuntu 12.04.

一个我不相信的版本已经发布了。我在Ubuntu 12.04上测试了python 2.7。

Found this solution at : http://code.activestate.com/recipes/439094-get-the-ip-address-associated-with-a-network-inter/

找到这个解决方案的网址是:http://code.activestate.com/recipes/439094-get- ip-address-联系簿。

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

Example Result:

结果示例:

get_ip_address('eth0') '38.113.228.130'

get_ip_address(eth0的)“38.113.228.130”

#14


8  

One simple way to produce "clean" output via command line utils:

一种通过命令行来产生“干净”输出的简单方法:

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

It will show all IPv4 addresses on the system.

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

#15


7  

FYI I can verify that the method:

我可以验证这个方法:

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

Works in OS X (10.6,10.5), Windows XP, and on a well administered RHEL department server. It did not work on a very minimal CentOS VM that I just do some kernel hacking on. So for that instance you can just check for a 127.0.0.1 address and in that case do the following:

在OS X (10.6,10.5), Windows XP,以及在一个管理良好的RHEL部门服务器上工作。它并没有在一个非常小的CentOS VM上运行,我只是做了一些内核黑客。对于这个例子,你可以检查一下127.0.0。0。0。1的地址,在这种情况下,做如下操作:

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

And then parse the ip address from the output. It should be noted that ifconfig is not in a normal user's PATH by default and that is why I give the full path in the command. I hope this helps.

然后从输出中解析ip地址。应该注意的是,ifconfig在默认情况下不是在正常用户的路径中,这就是为什么我在命令中给出了完整的路径。我希望这可以帮助。

#16


6  

I'm afraid there aren't any good platform independent ways to do this other than connecting to another computer and having it send you your IP address. For example: findmyipaddress. Note that this won't work if you need an IP address that's behind NAT unless the computer you're connecting to is behind NAT as well.

我担心,除了连接到另一台计算机并将你的IP地址发送给你之外,没有任何好的平*立的方式来完成这个任务。例如:findmyipaddress。请注意,如果您需要一个位于NAT后面的IP地址,那么这将不起作用,除非您连接的计算机也在NAT后面。

Here's one solution that works in Linux: get the IP address associated with a network interface.

这里有一个在Linux中工作的解决方案:获取与网络接口相关联的IP地址。

#17


6  

This will work on most linux boxes:

这将适用于大多数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()

#18


6  

import socket
[i[4][0] for i in socket.getaddrinfo(socket.gethostname(), None)]

#19


6  

This is a variant of UnkwnTech's answer -- it provides a get_local_addr() function, which returns the primary LAN ip address of the host. I'm posting it because this adds a number of things: ipv6 support, error handling, ignoring localhost/linklocal addrs, and uses a TESTNET addr (rfc5737) to connect to.

这是UnkwnTech的一个变体,它提供了get_local_addr()函数,该函数返回主机的主LAN ip地址。我发布它是因为这增加了很多东西:ipv6支持、错误处理、忽略localhost/linklocal addrs,以及使用TESTNET addr (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

#20


6  

Variation on ninjagecko's answer. This should work on any LAN that allows UDP broadcast and doesn't require access to an address on the LAN or internet.

变异ninjagecko的答案。这应该适用于任何允许UDP广播的局域网,而且不需要访问局域网或互联网上的地址。

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

#21


4  

127.0.1.1 is your real IP address. More generally speaking, a computer can have any number of IP addresses. You can filter them for private networks - 127.0.0.0/8, 10.0.0.0/8, 172.16.0.0/12 and 192.168.0.0/16.

127.0.1.1是您的真实IP地址。更一般地说,计算机可以有任意数量的IP地址。您可以将它们过滤到私有网络中——127.0.0.0/8、10.0.0 /8、172.16.0 /12和192.168.0 /16。

However, there is no cross-platform way to get all IP addresses. On Linux, you can use the SIOCGIFCONF ioctl.

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

#22


4  

A slight refinement of the commands version that uses the IP command, and returns IPv4 and IPv6 addresses:

对使用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)]

#23


4  

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:

这个答案是我个人尝试解决获取LAN IP的问题,因为socket.gethostbyname(socket.gethostname())也返回了127.0.0.1。这种方法不需要网络只是局域网连接。代码是用于Python 3的。x但是很容易转换成2。x。使用UDP广播:

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

#24


4  

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

你可以在GNU/Linux上使用命令“ip路由”来了解你当前的ip地址。

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.

这显示了在路由器/调制解调器上运行的DHCP服务器给接口的IP。通常“192.168.1.1 .1/24”是本地网络的IP,其中“24”指的是在掩码范围内DHCP服务器给出的正IP地址的范围。

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

这里有一个例子:注意,PyNotify只是一个附加的东西,它可以使我的观点完全正确,并且完全不需要。

#! /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

这样做的好处是,您不需要指定网络接口。这在运行socket服务器时非常有用。

You can install PyNotify using easy_install or even Pip:

您可以使用easy_install或甚至Pip安装PyNotify:

easy_install py-notify

or

pip install py-notify

or within python script/interpreter

或在python脚本/翻译

from pip import main

main(['install', 'py-notify'])

#25


3  

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

可以通过pip和easy_install提供网络面孔。(我知道,它不是在基地,但它可能值得安装。)

netifaces does have some oddities across platforms:

网友们在平台上确实有一些奇怪的地方:

  • The localhost/loop-back interface may not always be included (Cygwin).
  • localhost/ loopback接口可能不总是包含(Cygwin)。
  • Addresses are listed per-protocol (e.g., 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.
  • 每个协议(例如IPv4, IPv6)和协议都列出了每个接口。在某些系统(Linux)上,每个协议接口对都有它自己的关联接口(使用interface_name:n表示法),而在其他系统(Windows)上,单个接口将为每个协议提供一个地址列表。在这两种情况下都有一个协议列表,但它可能只包含一个元素。

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:

上面的代码没有将地址映射回它的接口名称(用于生成ebtables/iptables规则)。这里有一个版本,它将上面的信息和接口名称保持在一个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)

Enjoy!

享受吧!

#26


3  

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

要获得ip地址,您可以在python中直接使用shell命令:

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

#27


2  

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.

我必须解决这个问题,“如果IP地址是本地的还是不本地的”,我的第一个想法是建立一个IPs列表,它是本地的,然后与它匹配。这就是我对这个问题的看法。然而,我后来意识到有一个更直接的方法:尝试绑定那个IP,看看它是否有效。

_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).

我知道这并不能直接回答问题,但这对任何试图解决相关问题的人来说都是有帮助的,而且他们也在遵循同样的思路。这具有跨平台解决方案的优势(我认为)。

#28


2  

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

#29


2  

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

注意:这不是使用标准库,但是非常简单。

$ pip install pif

美元pip安装论坛

from pif import get_public_ip
get_public_ip()

#30


2  

import netifaces as ni 

ni.ifaddresses('eth0')
ip = ni.ifaddresses('eth0')[ni.AF_INET][0]['addr']
print(ip)

This will return you the IP address in the Ubuntu system as well as MacOS. The output will be the system IP address as like my IP: 192.168.1.10.

这将返回你的IP地址在Ubuntu系统和MacOS。输出将是系统IP地址,如我的IP: 192.168.1.10。

#1


312  

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

This won't work always (returns 127.0.0.1 on machines having the hostname in /etc/hosts as 127.0.0.1), a paliative would be what gimel shows, use socket.getfqdn() instead. Of course your machine needs a resolvable hostname.

这并不总是有效的(在/etc/主机上拥有主机名的机器上的返回127.0.0.1作为127.0.0.1),paliative将是gimel所展示的,使用socket.getfqdn()代替。当然,您的机器需要一个可解析的主机名。

#2


315  

I just found this but it seems a bit hackish, however they say tried it on *nix and I did on windows and it worked.

我刚发现了这个,但是看起来有点乱,不过他们说在*nix上试过了,我在windows上做了,而且成功了。

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

This assumes you have an internet access, and that there is no local proxy.

这假设您有一个internet访问,并且没有本地代理。

#3


125  

As an alias called myip, that should work everywhere:

作为一个别名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])'"
  • Works correctly with Python 2.x, Python 3.x, modern and old Linux distros, OSX/macOS and Windows for finding the current IPv4 address.
  • 正确使用Python 2。x,Python 3。x,现代和旧的Linux发行版,OSX/macOS和Windows寻找当前的IPv4地址。
  • Will not return the correct result for machines with multiple IP addresses, IPv6, no configured IP address or no internet access.
  • 对于具有多个IP地址、IPv6、没有配置IP地址或没有internet访问的机器,将不会返回正确的结果。

Same as above, but only the Python code:

和上面一样,但只有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])
  • This will throw an exception if no IP address is configured.
  • 如果没有配置IP地址,这将引发异常。

Version that will also work on LANs without an internet connection:

该版本也将在没有互联网连接的局域网中工作:

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

(thanks @ccpizza)

(感谢@ccpizza)


Background:

背景:

Using socket.gethostbyname(socket.gethostname()) did not work here, because one of the computers I was on had an /etc/hosts with duplicate entries and references to itself. socket.gethostbyname() only returns the last entry in /etc/hosts.

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

This was my initial attempt, which weeds out all addresses starting with "127.":

这是我最初的尝试,从“127”开始清除所有的地址。

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

This works with Python 2 and 3, on Linux and Windows, but does not deal with several network devices or IPv6. However, it stopped working on recent Linux distros, so I tried this alternative technique instead. It tries to connect to the Google DNS server at 8.8.8.8 at port 53:

这适用于Python 2和3,在Linux和Windows上,但不处理多个网络设备或IPv6。但是,它停止了最近的Linux发行版,所以我尝试了这种替代技术。它尝试连接到端口53的谷歌DNS服务器,在8.8.8.8:

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

Then I combined the two above techniques into a one-liner that should work everywhere, and created the myip alias and Python snippet at the top of this answer.

然后,我将上述两种技术组合成一行程序,在每个地方都可以工作,并在这个答案的顶部创建了myip别名和Python代码段。

With the increasing popularity of IPv6, and for servers with multiple network interfaces, using a third-party Python module for finding the IP address is probably both more robust and reliable than any of the techiques listed here.

随着IPv6越来越受欢迎,对于具有多个网络接口的服务器,使用第三方Python模块来查找IP地址可能比这里列出的任何技术都更加健壮和可靠。

#4


78  

You can use the netifaces module. Just type:

你可以使用这个网友模块。类型:

pip install netifaces

in your command shell and it will install itself on default Python installation.

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

Then you can use it like this:

然后你可以这样使用:

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

On my computer it printed:

我的电脑上印着:

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

Author of this module claims it should work on Windows, UNIX and Mac OS X.

该模块的作者声称它应该在Windows、UNIX和Mac OS X上运行。

#5


73  

This function returns the "primary" IP on the local box (the one with a default route).

此函数将返回本地框上的“主”IP(具有默认路由的)。

  • Does NOT need routable net access or any connection at all.
  • 不需要可路由的网络访问或任何连接。
  • Works even if all interfaces are unplugged from the network.
  • 即使所有的接口都从网络断开,也可以工作。
  • Does NOT need or even try to get anywhere else.
  • 不需要甚至尝试去其他地方。
  • Works with NAT, public, private, external, and internal IP's
  • 与NAT,公共,私有,外部,和内部IP的工作。
  • Pure Python 2 with no external dependencies.
  • 纯Python 2,没有外部依赖项。
  • Works on Linux, Windows, and OSX.
  • 在Linux、Windows和OSX上工作。

Python 2 or 3:

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

This returns a single IP which is the primary (the one with a default route). If you need instead all IP's attached to all interfaces (including localhost, etc), see this answer.

这将返回一个单独的IP,该IP是主服务器(具有默认路由的IP)。如果您需要所有的IP连接到所有的接口(包括本地主机等),请参见这个答案。

If you are behind a NAT firewall like your wifi box at home, then this will not show your public NAT IP, but instead your private NAT IP on the local network which has a default route to your local WIFI router; getting your wifi router's external IP would either require running this on THAT box, or connecting to an external service such as whatismyip.com/whatismyipaddress.com that could reflect back the IP... but that is completely different from the original question. :)

如果你在一个NAT防火墙后,比如你家里的wifi,那么这将不会显示你的公共NAT IP,而是你的私有NAT IP在本地网络上,它有一个默认路由到你本地的wifi路由器;获取你的wifi路由器的外部IP要么需要在那个盒子上运行这个,要么连接到一个外部服务,比如whatismyip.com/whatismyipaddress.com,它可以反射IP…但这与最初的问题完全不同。:)

Updated connect() call per Pedro's suggestion in comments. (If you need a specific license statement, this is public domain/free for any use, or MIT/CC2-BY-SA per Stack Overflow's code/content license at your option.)

在评论中更新connect()调用per Pedro的建议。(如果你需要一个特定的许可声明,这是一个公共域/免费的任何使用,或者麻省理工/CC2-BY-SA每个Stack Overflow的代码/内容许可你的选择。)

#6


47  

Socket API method

套接字API方法

see https://*.com/a/28950776/711085

参见https://*.com/a/28950776/711085

Downsides:

缺点:

  • Not cross-platform.
  • 不是跨平台。
  • Requires more fallback code, tied to existence of particular addresses on the internet
  • 需要更多的后备代码,与互联网上特定地址的存在联系在一起。
  • This will also not work if you're behind a NAT
  • 如果你在NAT后面,这也不会起作用。
  • Probably creates a UDP connection, not independent of (usually ISP's) DNS availability (see other answers for ideas like using 8.8.8.8: Google's (coincidentally also DNS) server)
  • 可能会创建一个UDP连接,而不是独立于(通常是ISP的)DNS可用性(见其他的答案,比如使用8.8.8.8:谷歌的(碰巧也是DNS)服务器)
  • Make sure you make the destination address UNREACHABLE, like a numeric IP address that is spec-guaranteed to be unused. Do NOT use some domain like fakesubdomain.google.com or somefakewebsite.com; you'll still be spamming that party (now or in the future), and spamming your own network boxes as well in the process.
  • 确保您的目标地址是不可访问的,就像一个指定的数字IP地址,保证不被使用。不要使用一些域名,比如fakesubdomain.google.com或somefakewebsite.com;你仍然会在那个聚会(现在或将来)发送垃圾邮件,并且在这个过程中发送你自己的网络邮箱。

Reflector method

反射器方法

(Do note that this does not answer the OP's question of the local IP address, e.g. 192.168...; it gives you your public IP address, which might be more desirable depending on use case.)

(请注意,这并不能回答OP对本地IP地址的问题,例如192.168…;它提供了您的公共IP地址,根据用例,这可能更可取。

You can query some site like whatismyip.com (but with an API), such as:

您可以查询一些站点,如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)

or if using python2:

或者使用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)

Advantages:

优点:

  • One upside of this method is it's cross-platform
  • 这种方法的一个优点是它是跨平台的。
  • It works from behind ugly NATs (e.g. your home router).
  • 它在丑陋的NATs(比如你的家庭路由器)后面工作。

Disadvantages (and workarounds):

缺点(解决方案):

  • Requires this website to be up, the format to not change (almost certainly won't), and your DNS servers to be working. One can mitigate this issue by also querying other third-party IP address reflectors in case of failure.
  • 需要这个网站的启动,格式不改变(几乎肯定不会),和你的DNS服务器工作。如果出现故障,可以通过查询其他第三方IP地址反射器来缓解这个问题。
  • Possible attack vector if you don't query multiple reflectors (to prevent a compromised reflector from telling you that your address is something it's not), or if you don't use HTTPS (to prevent a man-in-the-middle attack pretending to be the server)
  • 如果您不查询多个反射器(防止反射器告诉您您的地址是某件事),或者您不使用HTTPS(为了防止中间人攻击假装是服务器),那么可能的攻击向量就会发生。

edit: Though initially I thought these methods were really bad (unless you use many fallbacks, the code may be irrelevant many years from now), it does pose the question "what is the internet?". A computer may have many interfaces pointing to many different networks. For a more thorough description of the topic, google for gateways and routes. A computer may be able to access an internal network via an internal gateway, or access the world-wide web via a gateway on for example a router (usually the case). The local IP address that the OP asks about is only well-defined with respect to a single link layer, so you have to specify that ("is it the network card, or the ethernet cable, which we're talking about?"). There may be multiple non-unique answers to this question as posed. However the global IP address on the world-wide web is probably well-defined (in the absence of massive network fragmentation): probably the return path via the gateway which can access the TLDs.

编辑:虽然一开始我认为这些方法很糟糕(除非你使用了很多的退路,但这些代码可能在很多年以后都是不相关的),它确实提出了一个问题:“什么是互联网?”计算机可能有许多接口指向许多不同的网络。为了更详细地描述这个主题,谷歌为网关和路由。计算机可以通过内部网关访问内部网络,或者通过网关(例如路由器)访问全球网络(通常是这样)。OP所要求的本地IP地址仅对单个链路层进行了定义,所以您必须指定(“是网卡还是以太网线,我们正在讨论的?”)。对于这个问题,可能有多个非唯一的答案。然而,全球网络上的全球IP地址可能是明确定义的(在没有大规模网络碎片的情况下):可能通过网关的返回路径可以访问TLDs。

#7


39  

If the computer has a route to the Internet, this will always work to get the preferred local ip address, even if /etc/hosts is not set correctly.

如果计算机有通向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]

#8


37  

On Linux:

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

#9


26  

im using following module:

我使用以下模块:

#!/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

Tested with windows and linux (and doesnt require additional modules for those) intended for use on systems which are in a single IPv4 based LAN.

使用windows和linux测试(并且不需要额外的模块),用于在一个基于IPv4的局域网中使用的系统。

The fixed list of interface names does not work for recent linux versions, which have adopted the systemd v197 change regarding predictable interface names as pointed out by Alexander. In such cases, you need to manually replace the list with the interface names on your system, or use another solution like netifaces.

接口名称的固定列表不适用于最近的linux版本,该版本采用了由Alexander指出的可预测接口名称的systemd v197更改。在这种情况下,您需要手动地将该列表替换为系统上的接口名称,或者使用其他的解决方案,如网络用户。

#10


25  

I use this on my ubuntu machines:

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

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

This doesn't work.

这并不工作。

#11


20  

If you don't want to use external packages and don't want to rely on outside Internet servers, this might help. It's a code sample that I found on Google Code Search and modified to return required information:

如果您不想使用外部包,并且不想依赖于外部Internet服务器,这可能会有所帮助。这是我在谷歌代码搜索和修改后发现的代码样本,以返回所需的信息:

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

Usage:

用法:

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

As it relies on windll, this will work only on Windows.

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

#12


14  

On Debian (tested) and I suspect most Linux's..

在Debian(测试)上,我怀疑大多数Linux。

import commands

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

On MS Windows (tested)

在MS Windows(测试)

import socket

socket.gethostbyname(socket.gethostname())

#13


11  

A version I do not believe that has been posted yet. I tested with python 2.7 on Ubuntu 12.04.

一个我不相信的版本已经发布了。我在Ubuntu 12.04上测试了python 2.7。

Found this solution at : http://code.activestate.com/recipes/439094-get-the-ip-address-associated-with-a-network-inter/

找到这个解决方案的网址是:http://code.activestate.com/recipes/439094-get- ip-address-联系簿。

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

Example Result:

结果示例:

get_ip_address('eth0') '38.113.228.130'

get_ip_address(eth0的)“38.113.228.130”

#14


8  

One simple way to produce "clean" output via command line utils:

一种通过命令行来产生“干净”输出的简单方法:

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

It will show all IPv4 addresses on the system.

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

#15


7  

FYI I can verify that the method:

我可以验证这个方法:

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

Works in OS X (10.6,10.5), Windows XP, and on a well administered RHEL department server. It did not work on a very minimal CentOS VM that I just do some kernel hacking on. So for that instance you can just check for a 127.0.0.1 address and in that case do the following:

在OS X (10.6,10.5), Windows XP,以及在一个管理良好的RHEL部门服务器上工作。它并没有在一个非常小的CentOS VM上运行,我只是做了一些内核黑客。对于这个例子,你可以检查一下127.0.0。0。0。1的地址,在这种情况下,做如下操作:

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

And then parse the ip address from the output. It should be noted that ifconfig is not in a normal user's PATH by default and that is why I give the full path in the command. I hope this helps.

然后从输出中解析ip地址。应该注意的是,ifconfig在默认情况下不是在正常用户的路径中,这就是为什么我在命令中给出了完整的路径。我希望这可以帮助。

#16


6  

I'm afraid there aren't any good platform independent ways to do this other than connecting to another computer and having it send you your IP address. For example: findmyipaddress. Note that this won't work if you need an IP address that's behind NAT unless the computer you're connecting to is behind NAT as well.

我担心,除了连接到另一台计算机并将你的IP地址发送给你之外,没有任何好的平*立的方式来完成这个任务。例如:findmyipaddress。请注意,如果您需要一个位于NAT后面的IP地址,那么这将不起作用,除非您连接的计算机也在NAT后面。

Here's one solution that works in Linux: get the IP address associated with a network interface.

这里有一个在Linux中工作的解决方案:获取与网络接口相关联的IP地址。

#17


6  

This will work on most linux boxes:

这将适用于大多数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()

#18


6  

import socket
[i[4][0] for i in socket.getaddrinfo(socket.gethostname(), None)]

#19


6  

This is a variant of UnkwnTech's answer -- it provides a get_local_addr() function, which returns the primary LAN ip address of the host. I'm posting it because this adds a number of things: ipv6 support, error handling, ignoring localhost/linklocal addrs, and uses a TESTNET addr (rfc5737) to connect to.

这是UnkwnTech的一个变体,它提供了get_local_addr()函数,该函数返回主机的主LAN ip地址。我发布它是因为这增加了很多东西:ipv6支持、错误处理、忽略localhost/linklocal addrs,以及使用TESTNET addr (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

#20


6  

Variation on ninjagecko's answer. This should work on any LAN that allows UDP broadcast and doesn't require access to an address on the LAN or internet.

变异ninjagecko的答案。这应该适用于任何允许UDP广播的局域网,而且不需要访问局域网或互联网上的地址。

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

#21


4  

127.0.1.1 is your real IP address. More generally speaking, a computer can have any number of IP addresses. You can filter them for private networks - 127.0.0.0/8, 10.0.0.0/8, 172.16.0.0/12 and 192.168.0.0/16.

127.0.1.1是您的真实IP地址。更一般地说,计算机可以有任意数量的IP地址。您可以将它们过滤到私有网络中——127.0.0.0/8、10.0.0 /8、172.16.0 /12和192.168.0 /16。

However, there is no cross-platform way to get all IP addresses. On Linux, you can use the SIOCGIFCONF ioctl.

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

#22


4  

A slight refinement of the commands version that uses the IP command, and returns IPv4 and IPv6 addresses:

对使用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)]

#23


4  

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:

这个答案是我个人尝试解决获取LAN IP的问题,因为socket.gethostbyname(socket.gethostname())也返回了127.0.0.1。这种方法不需要网络只是局域网连接。代码是用于Python 3的。x但是很容易转换成2。x。使用UDP广播:

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

#24


4  

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

你可以在GNU/Linux上使用命令“ip路由”来了解你当前的ip地址。

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.

这显示了在路由器/调制解调器上运行的DHCP服务器给接口的IP。通常“192.168.1.1 .1/24”是本地网络的IP,其中“24”指的是在掩码范围内DHCP服务器给出的正IP地址的范围。

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

这里有一个例子:注意,PyNotify只是一个附加的东西,它可以使我的观点完全正确,并且完全不需要。

#! /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

这样做的好处是,您不需要指定网络接口。这在运行socket服务器时非常有用。

You can install PyNotify using easy_install or even Pip:

您可以使用easy_install或甚至Pip安装PyNotify:

easy_install py-notify

or

pip install py-notify

or within python script/interpreter

或在python脚本/翻译

from pip import main

main(['install', 'py-notify'])

#25


3  

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

可以通过pip和easy_install提供网络面孔。(我知道,它不是在基地,但它可能值得安装。)

netifaces does have some oddities across platforms:

网友们在平台上确实有一些奇怪的地方:

  • The localhost/loop-back interface may not always be included (Cygwin).
  • localhost/ loopback接口可能不总是包含(Cygwin)。
  • Addresses are listed per-protocol (e.g., 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.
  • 每个协议(例如IPv4, IPv6)和协议都列出了每个接口。在某些系统(Linux)上,每个协议接口对都有它自己的关联接口(使用interface_name:n表示法),而在其他系统(Windows)上,单个接口将为每个协议提供一个地址列表。在这两种情况下都有一个协议列表,但它可能只包含一个元素。

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:

上面的代码没有将地址映射回它的接口名称(用于生成ebtables/iptables规则)。这里有一个版本,它将上面的信息和接口名称保持在一个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)

Enjoy!

享受吧!

#26


3  

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

要获得ip地址,您可以在python中直接使用shell命令:

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

#27


2  

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.

我必须解决这个问题,“如果IP地址是本地的还是不本地的”,我的第一个想法是建立一个IPs列表,它是本地的,然后与它匹配。这就是我对这个问题的看法。然而,我后来意识到有一个更直接的方法:尝试绑定那个IP,看看它是否有效。

_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).

我知道这并不能直接回答问题,但这对任何试图解决相关问题的人来说都是有帮助的,而且他们也在遵循同样的思路。这具有跨平台解决方案的优势(我认为)。

#28


2  

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

#29


2  

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

注意:这不是使用标准库,但是非常简单。

$ pip install pif

美元pip安装论坛

from pif import get_public_ip
get_public_ip()

#30


2  

import netifaces as ni 

ni.ifaddresses('eth0')
ip = ni.ifaddresses('eth0')[ni.AF_INET][0]['addr']
print(ip)

This will return you the IP address in the Ubuntu system as well as MacOS. The output will be the system IP address as like my IP: 192.168.1.10.

这将返回你的IP地址在Ubuntu系统和MacOS。输出将是系统IP地址,如我的IP: 192.168.1.10。