Поиск локальных IP-адресов с использованием Python stdlib

Как я могу найти локальные IP-адреса (например, 192.168.x.x или 10.0.x.x) на платформе Python самостоятельно и использовать только стандартную библиотеку?

Ответ 1

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

Это не будет работать всегда (возвращает 127.0.0.1 на машинах, имеющих имя хоста в /etc/hosts как 127.0.0.1), палитрация будет тем, что показывает gimel, вместо этого используйте socket.getfqdn(). Конечно, ваша машина нуждается в разрешимом имени хоста.

Ответ 2

Я только что нашел это, но кажется немного взломанным, однако они говорят, что попробовали его на * nix, и я сделал это на окнах, и это сработало.

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

Это предполагает, что у вас есть доступ в Интернет, и что нет локального прокси.

Ответ 3

Этот метод возвращает "основной" IP-адрес локального ящика (тот, который имеет маршрут по умолчанию).

  • НЕ нуждается в маршрутизируемом сетевом доступе или любом соединении вообще.
  • Работает, даже если все интерфейсы отключены от сети.
  • НЕ нужно или даже пытаться добраться куда-нибудь еще.
  • Работает с NAT, публичными, частными, внешними и внутренними IP
  • Чистый Python 2 (или 3) без внешних зависимостей.
  • Работает на 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-адреса были подключены ко всем интерфейсам (включая localhost и т.д.), Посмотрите этот ответ.

Если вы находитесь за брандмауэром NAT, таким как домашний Wi-Fi, тогда он не будет показывать ваш общедоступный IP-адрес NAT, а вместо этого будет использовать ваш частный IP-адрес в локальной сети, который имеет маршрут по умолчанию к локальному маршрутизатору WIFI; для получения внешнего IP-адреса вашего маршрутизатора Wi-Fi потребуется либо запустить его в поле THAT, либо подключиться к внешней службе, такой как whatismyip.com/whatismyipaddress.com, которая может отражать IP-адрес... но это полностью отличается от первоначального вопроса. :)

Обновлен вызов connect() для каждого предложения Pedro в комментариях. (Если вам нужно конкретное лицензионное выражение, это общедоступное/бесплатное для любого использования или MIT/CC2-BY-SA для кода/лицензии на контент по вашему выбору.)

Ответ 4

Как псевдоним 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, без настроенного IP-адреса или без доступа в Интернет.

То же, что и выше, но только код 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])
  • Это вызовет исключение, если IP-адрес не настроен.

Версия, которая также будет работать в локальных сетях без подключения к интернету:

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()) здесь не работало, потому что на одном из моих компьютеров был 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])

Это работает с Python 2 и 3, в Linux и Windows, но не работает с несколькими сетевыми устройствами или IPv6. Однако на последних дистрибутивах Linux он перестал работать, поэтому я попробовал этот альтернативный метод. Он пытается подключиться к DNS-серверу Google по адресу 8.8.8.8 через порт 53:

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 которая должна работать везде, и создал псевдоним myip и фрагмент Python в верхней части этого ответа.

С ростом популярности IPv6 и для серверов с несколькими сетевыми интерфейсами использование стороннего модуля Python для нахождения IP-адреса, вероятно, является одновременно более надежным и надежным, чем любой из перечисленных здесь методов.

Ответ 5

Вы можете использовать модуль netifaces. Просто введите:

pip install netifaces

в вашей командной оболочке, и он будет установлен по умолчанию при установке 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.

Ответ 6

Метод Socket API

см. fooobar.com/questions/18581/...

Недостатки:

  • Не кроссплатформенный.
  • Требуется дополнительный резервный код, связанный с наличием определенных адресов в интернете
  • Это также не будет работать, если вы находитесь за NAT
  • Вероятно, создает UDP-соединение, не зависящее от доступности (обычно ISP) DNS (см. Другие ответы на такие идеи, как использование 8.8.8.8: сервер Google (также DNS))
  • Убедитесь, что вы сделали адрес назначения недоступным, как числовой IP-адрес, который гарантированно не будет использоваться. НЕ используйте какой-либо домен, например, fakesubdomain.google.com или somefakewebsite.com; вы все равно будете рассылать спам этой стороне (сейчас или в будущем), а также спамить свои собственные сетевые блоки в процессе.

Рефлекторный метод

(Обратите внимание, что это не отвечает на вопрос 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-адресов в случае сбоя.
  • Возможный вектор атаки, если вы не запрашиваете несколько отражателей (чтобы не дать скомпрометированному отражателю сказать, что ваш адрес является чем-то другим), или если вы не используете HTTPS (чтобы предотвратить атаку типа "человек посередине" быть сервером)

редактировать: хотя изначально я думал, что эти методы были действительно плохими (если вы не используете много запасных вариантов, код может быть неактуальным через много лет), он ставит вопрос "что такое Интернет?". Компьютер может иметь много интерфейсов, указывающих на множество различных сетей. Для более подробного описания темы, Google для gateways and routes. Компьютер может иметь доступ к внутренней сети через внутренний шлюз или к всемирной паутине через шлюз, например, на маршрутизаторе (обычно это так). Локальный IP-адрес, о котором запрашивает OP, четко определен только для одного канального уровня, поэтому вы должны указать это ("речь идет о сетевой карте или кабеле Ethernet, о которых мы говорим?"), На поставленный вопрос может быть несколько неуникальных ответов. Однако глобальный IP-адрес во всемирной сети, вероятно, четко определен (в отсутствие массовой фрагментации сети): возможно, обратный путь через шлюз, который может получить доступ к TLD.

Ответ 7

Если компьютер имеет маршрут в Интернет, это всегда будет работать, чтобы получить предпочтительный локальный IP-адрес, даже если /etc/hosts установлены неправильно.

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

В 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

im, используя следующий модуль:

#!/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 (и для них не требуются дополнительные модули) предназначенные для использования в системах, находящихся в одной локальной сети на основе IPv4.

Фиксированный список имен интерфейсов не работает для последних версий Linux, которые приняли изменение systemd v197 относительно предсказуемых имен интерфейсов, как указано Alexander. В таких случаях вам нужно вручную заменить список именами интерфейса в вашей системе или использовать другое решение, например netifaces.

Ответ 10

Я использую это на моих машинах Ubuntu:

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

Это не работает

Ответ 11

Если вы не хотите использовать внешние пакеты и не хотите полагаться на внешние интернет-серверы, это может помочь. Это образец кода, который я нашел на Google Code Search и изменен для возврата требуемой информации:

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.

Ответ 12

Версия, которую я не верю, была опубликована. Я тестировал с python 2.7 на Ubuntu 12.04.

Нашел это решение по адресу: 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'

Ответ 13

В Debian (тестируется), и я подозреваю, что большинство Linux..

import commands

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

В MS Windows (протестировано)

import socket

socket.gethostbyname(socket.gethostname())

Ответ 14

Вариант ответа ниндзягеко. Это должно работать в любой локальной сети, которая разрешает широковещательную рассылку 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())

Ответ 15

Я боюсь, что нет никаких хороших независимых для платформы способов сделать это, кроме как подключиться к другому компьютеру и отправить ему ваш IP-адрес. Например: findmyipaddress. Обратите внимание, что это не будет работать, если вам нужен IP-адрес, расположенный за NAT, если только компьютер, к которому вы подключаетесь, находится за NAT.

Здесь одно решение, которое работает в Linux: получить IP-адрес, связанный с сетевым интерфейсом.

Ответ 16

Один простой способ произвести "чистый" вывод через utils командной строки:

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

Он отобразит все IPv4-адреса в системе.

Ответ 17

FYI Я могу проверить, что метод:

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

Работает в OS X (10.6, 10.5), Windows XP и на хорошо управляемом сервере отдела RHEL. Он не работал на очень минимальной виртуальной виртуальной машине CentOS, и я просто делаю взлом ядра. Поэтому для этого примера вы можете просто проверить адрес 127.0.0.1 и в этом случае сделать следующее:

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

И затем проанализируйте ip-адрес с выхода. Следует отметить, что ifconfig по умолчанию не является обычным пользователем PATH, и именно поэтому я даю полный путь в команде. Надеюсь, это поможет.

Ответ 18

Это вариант ответа UnkwnTech - он предоставляет функцию get_local_addr(), которая возвращает основной 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

Ответ 19

Это будет работать на большинстве 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()

Ответ 20

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

Ответ 21

Этот ответ - моя личная попытка решить проблему получения IP-адреса LAN, поскольку 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())

Ответ 22

127.0.1.1 - ваш реальный IP-адрес. В более общем плане компьютер может иметь любое количество IP-адресов. Вы можете отфильтровать их для частных сетей - 127.0.0.0/8, 10.0.0.0/8, 172.16.0.0/12 и 192.168.0.0/16.

Однако нет кросс-платформенного способа получить все IP-адреса. В Linux вы можете использовать SIOCGIFCONF ioctl.

Ответ 23

Небольшое уточнение версии команд, использующей команду 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)]

Ответ 24

Ну, вы можете использовать команду "ip route" в GNU/Linux, чтобы узнать свой текущий IP-адрес.

Это показывает IP-адрес, предоставляемый интерфейсу сервером DHCP, запущенным на маршрутизаторе/модемом. Обычно "192.168.1.1/24" - это IP для локальной сети, где "24" означает диапазон возможных IP-адресов, заданных сервером DHCP в пределах диапазона маски.

Вот пример: обратите внимание, что 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()    

Преимущество этого заключается в том, что вам не нужно указывать сетевой интерфейс. Это очень полезно при запуске сервера сокетов

Вы можете установить PyNotify с помощью easy_install или даже Pip:

easy_install py-notify

или

pip install py-notify

или внутри python script/interpreter

from pip import main

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

Ответ 25

Примечание. Это не использует стандартную библиотеку, но довольно просто.

$pip install pif

from pif import get_public_ip
get_public_ip()

Ответ 26

netifaces доступен через pip и easy_install. (Я знаю, это не в базе, но это может стоить установки.)

netifaces имеет некоторые странности на разных платформах:

  • Интерфейс localhost/loop-back может не всегда включаться (Cygwin).
  • Адреса указаны для каждого протокола (например, IPv4, IPv6), а протоколы перечислены для каждого интерфейса. В некоторых системах (Linux) каждая пара протокольных интерфейсов имеет свой собственный связанный интерфейс (с использованием нотации interface_name: n), а в других системах (Windows) один интерфейс будет иметь список адресов для каждого протокола. В обоих случаях есть список протоколов, но он может содержать только один элемент.

Вот какой код netifaces для воспроизведения:

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.

Приведенный выше код не отображает адрес обратно в его имя интерфейса (полезно для генерации правил ebtables/iptables на лету). Итак, вот версия, которая сохраняет указанную выше информацию с именем интерфейса в кортеже:

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]

И нет, я не люблю списки. Это именно то, как работает мой мозг в наши дни.

Следующий фрагмент распечатает все:

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)

Наслаждайтесь!

Ответ 27

Чтобы получить ip-адрес, вы можете использовать команду оболочки непосредственно в 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()

Ответ 28

import netifaces as ni 

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

Это вернет вам IP-адрес в системе Ubuntu, а также MacOS. Вывод будет IP-адрес системы, как мой IP: 192.168.1.10.

Ответ 29

Если вы ищете IPV4-адрес, отличный от вашего локального IP-адреса 127.0.0.1, вот несколько полезных кодов Python:

import subprocess
address = subprocess.check_output(['hostname', '-s', '-I'])
address = address.decode('utf-8') 
address=address[:-1]

Который также можно записать в одну строку:

address = subprocess.check_output(['hostname', '-s', '-I']).decode('utf-8')[:-1]

Даже если вы поместите localhost в /etc/hostname, код все равно даст ваш локальный IP-адрес.

Ответ 30

Мне пришлось решить проблему "Поясните, является ли IP-адрес локальным или нет", и моя первая мысль заключалась в том, чтобы создать список IP-адресов, которые были локальными, а затем сопоставлены с ним. Вот что привело меня к этому вопросу. Однако позже я понял, что есть более прямой способ сделать это: попробуйте связать на этом 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

Я знаю, что это не отвечает на вопрос напрямую, но это должно быть полезно для всех, кто пытается решить соответствующий вопрос и кто следит за тем же путем. У этого есть преимущество быть кросс-платформенным решением (я думаю).