Как я могу получить IP-адрес eth0 в Python?

При возникновении ошибки в Python script в Unix отправляется электронное письмо.

Мне было предложено добавить {Testing Environment} в строку темы письма, если IP-адрес 192.168.100.37, который является сервером тестирования. Таким образом, мы можем иметь одну версию script и способ узнать, поступает ли почта из испорченных данных на тестовом сервере.

Однако, когда я google, я продолжаю находить этот код:

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

Однако это дает мне IP-адрес 127.0.1.1. Когда я использую ifconfig, я получаю это

eth0      Link encap:Ethernet  HWaddr 00:1c:c4:2c:c8:3e
          inet addr:192.168.100.37  Bcast:192.168.100.255  Mask:255.255.255.0
          UP BROADCAST RUNNING MULTICAST  MTU:1500  Metric:1
          RX packets:75760697 errors:0 dropped:411180 overruns:0 frame:0
          TX packets:23166399 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:1000
          RX bytes:59525958247 (59.5 GB)  TX bytes:10142130096 (10.1 GB)
          Interrupt:19 Memory:f0500000-f0520000

lo        Link encap:Local Loopback
          inet addr:127.0.0.1  Mask:255.0.0.0
          UP LOOPBACK RUNNING  MTU:16436  Metric:1
          RX packets:25573544 errors:0 dropped:0 overruns:0 frame:0
          TX packets:25573544 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:0
          RX bytes:44531490070 (44.5 GB)  TX bytes:44531490070 (44.5 GB)

Во-первых, я не знаю, откуда он получил 127.0.1.1, но в любом случае это не то, что я хочу. Когда я google, я продолжаю приходить к тому же синтаксису, Bash сценарии или сетевые файлы, и я пытаюсь использовать стандартные библиотеки.

Итак, как я могу получить IP-адрес eth0 в Python?

Ответ 1

Два метода:

Метод # 1 (используйте внешний пакет)

Вам нужно задать IP-адрес, привязанный к вашему интерфейсу eth0. Это доступно из пакета netifaces

import netifaces as ni
ni.ifaddresses('eth0')
ip = ni.ifaddresses('eth0')[ni.AF_INET][0]['addr']
print ip  # should print "192.168.100.37"

Вы также можете получить список всех доступных интерфейсов через

ni.interfaces()

Метод № 2 (без внешнего пакета)

Здесь можно получить IP-адрес без использования пакета python:

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')  # '192.168.0.110'

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

if app.config['ENV'] == 'production':
  #send production email
else:
  #send development email

Ответ 2

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

import socket
def get_ip_address():
    s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
    s.connect(("8.8.8.8", 80))
    return s.getsockname()[0]

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

Ответ 3

Простой подход, который возвращает строку с ip-адресами для интерфейсов:

from subprocess import check_output

ips = check_output(['hostname', '--all-ip-addresses'])

для получения дополнительной информации см. hostname.

Ответ 5

Поскольку большинство ответов используют ifconfig для извлечения IPv4 из интерфейса eth0, который устарел в пользу ip addr, вместо этого можно использовать следующий код:

import os

ipv4 = os.popen('ip addr show eth0 | grep "\<inet\>" | awk \'{ print $2 }\' | awk -F "/" \'{ print $1 }\'').read().strip()
ipv6 = os.popen('ip addr show eth0 | grep "\<inet6\>" | awk \'{ print $2 }\' | awk -F "/" \'{ print $1 }\'').read().strip()

UPDATE:

В качестве альтернативы вы можете перенести часть задачи синтаксического анализа на интерпретатор python, используя split() вместо grep и awk, поскольку @serg указывает в комментарии:

import os

ipv4 = os.popen('ip addr show eth0').read().split("inet ")[1].split("/")[0]
ipv6 = os.popen('ip addr show eth0').read().split("inet6 ")[1].split("/")[0]

Но в этом случае вам нужно проверить границы массива, возвращаемые каждым вызовом split().

ОБНОВЛЕНИЕ 2:

Другая версия с использованием регулярного выражения:

import os
import re

ipv4 = re.search(re.compile(r'(?<=inet )(.*)(?=\/)', re.M), os.popen('ip addr show eth0').read()).groups()[0]
ipv6 = re.search(re.compile(r'(?<=inet6 )(.*)(?=\/)', re.M), os.popen('ip addr show eth0').read()).groups()[0]

Ответ 6

попробуйте под кодом, он работает для меня в Mac10.10.2:

import subprocess

if __name__ == "__main__":
    result = subprocess.check_output('ifconfig en0 |grep -w inet', shell=True) # you may need to use eth0 instead of en0 here!!!
    print 'output = %s' % result.strip()
    # result = None
    ip = ''
    if result:
        strs = result.split('\n')
        for line in strs:
            # remove \t, space...
            line = line.strip()
            if line.startswith('inet '):
                a = line.find(' ')
                ipStart = a+1
                ipEnd = line.find(' ', ipStart)
                if a != -1 and ipEnd != -1:
                    ip = line[ipStart:ipEnd]
                    break
    print 'ip = %s' % ip

Ответ 7

Основываясь на ответе @jeremyjjbrown, еще одна версия, которая убирает за собой, как упоминалось в комментариях к его ответу. Эта версия также позволяет предоставлять другой адрес сервера для использования в частных внутренних сетях и т.д.

import socket

def get_my_ip_address(remote_server="google.com"):
    """
    Return the/a network-facing IP number for this system.
    """
    with socket.socket(socket.AF_INET, socket.SOCK_DGRAM) as s: 
        s.connect((remote_server, 80))
        return s.getsockname()[0]

Ответ 8

Это сработало для меня

 import subprocess
 my_ip = subprocess.Popen(['ifconfig eth0 | awk "/inet /" | cut -d":" -f 2 | cut -d" " -f1'], stdout=subprocess.PIPE, shell=True)
 (IP,errors) = my_ip.communicate()
 my_ip.stdout.close()
 print IP

Ответ 9

Найдите IP-адрес первой записи eth/wlan в ifconfig, что RUNNING:

import itertools
import os
import re

def get_ip():
    f = os.popen('ifconfig')
    for iface in [' '.join(i) for i in iter(lambda: list(itertools.takewhile(lambda l: not l.isspace(),f)), [])]:
        if re.findall('^(eth|wlan)[0-9]',iface) and re.findall('RUNNING',iface):
            ip = re.findall('(?<=inet\saddr:)[0-9\.]+',iface)
            if ip:
                return ip[0]
    return False

Ответ 10

Это результат ifconfig:

[email protected]:~ $ ifconfig
eth0: flags=4163<UP,BROADCAST,RUNNING,MULTICAST>  mtu 1500
        inet 192.168.2.24  netmask 255.255.255.0  broadcast 192.168.2.255
        inet6 fe80::88e9:4d2:c057:2d5f  prefixlen 64  scopeid 0x20<link>
        ether b8:27:eb:d0:9a:f3  txqueuelen 1000  (Ethernet)
        RX packets 261861  bytes 250818555 (239.1 MiB)
        RX errors 0  dropped 6  overruns 0  frame 0
        TX packets 299436  bytes 280053853 (267.0 MiB)
        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0

lo: flags=73<UP,LOOPBACK,RUNNING>  mtu 65536
        inet 127.0.0.1  netmask 255.0.0.0
        inet6 ::1  prefixlen 128  scopeid 0x10<host>
        loop  txqueuelen 1000  (Local Loopback)
        RX packets 74  bytes 16073 (15.6 KiB)
        RX errors 0  dropped 0  overruns 0  frame 0
        TX packets 74  bytes 16073 (15.6 KiB)
        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0

wlan0: flags=4099<UP,BROADCAST,MULTICAST>  mtu 1500
        ether b8:27:eb:85:cf:a6  txqueuelen 1000  (Ethernet)
        RX packets 0  bytes 0 (0.0 B)
        RX errors 0  dropped 0  overruns 0  frame 0
        TX packets 0  bytes 0 (0.0 B)
        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0

[email protected]:~ $ 

Немного подрезав вывод, имеем:

[email protected]:~ $ 
[email protected]:~ $ ifconfig eth0 | grep "inet 192" | cut -c 14-25
192.168.2.24
[email protected]:~ $ 
[email protected]:~ $ 

Теперь мы можем перейти на python и сделать:

import os
mine = os.popen('ifconfig eth0 | grep "inet 192" | cut -c 14-25')
myip = mine.read()
print (myip)