web-dev-qa-db-ja.com

Pythonでeth0のIPアドレスを取得するにはどうすればよいですか?

UnixのPythonスクリプトでエラーが発生すると、電子メールが送信されます。

IPアドレスがテストサーバーである192.168.100.37である場合、電子メールの件名に{Testing Environment}を追加するように求められました。このようにして、スクリプトの1つのバージョンと、テストサーバー上の混乱したデータから電子メールが送信されているかどうかを確認する方法を使用できます。

ただし、グーグルで検索すると、次のコードを見つけ続けます。

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

ただし、それは127.0.1.1のIPアドレスを提供します。 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を取得したかわかりませんが、どちらの方法でもそれは私が望むものではありません。私がグーグルで検索するとき、私は同じ構文 Bash scriptsまたはnetifacesを使い続け、標準ライブラリを使用しようとしています。

では、Pythonでeth0のIPアドレスを取得するにはどうすればよいですか?

58
Memor-X

2つの方法:

方法#1(外部パッケージを使用)

eth0インターフェイスにバインドされているIPアドレスを要求する必要があります。これは 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(外部パッケージなし)

pythonパッケージを使用せずにIPアドレスを取得する方法は次のとおりです。

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
148
Martin Konecny

または、名前を知らなくてもネットワークに接続するために使用されるインターフェイスの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へのルートを持つ必要はありません。ソケットを開くだけで、データは送信しません。

96
jeremyjjbrown

インターフェイスのIPアドレスを含む文字列を返す簡単な方法は次のとおりです。

from subprocess import check_output

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

詳細については、 hostname を参照してください。

25
Alexander

Unixでのみ作業する必要がある場合は、システムコールを使用できます(参照Stack.Overflow質問Bashを使用してIPアドレスのみを取得するifconfigを解析)):

import os
f = os.popen('ifconfig eth0 | grep "inet\ addr" | cut -d: -f2 | cut -d" " -f1')
your_ip=f.read()
16
olmerg

ほとんどの回答はifconfigを使用してeth0インターフェースからIPv4を抽出しますが、これは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()

更新:

または、コメントで@sergが指摘しているように、grepとawkの代わりにsplit()を使用して、解析タスクの一部をpythonインタープリターにシフトできます。

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

以下のコードを試してください、それはMac10.10.2で私のために動作します:

import subprocess

if __== "__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
2
xiaoweiz

@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]
1
Steve Cohen

実行中のifconfigで最初のeth/wlanエントリのIPアドレスを見つけます。

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
0
Giles Greenway

それは私のために働いた

 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
0
Abhijit

これはifconfigの結果です:

pi@raspberrypi:~ $ 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

pi@raspberrypi:~ $ 

出力を少しカットすると、次のようになります。

pi@raspberrypi:~ $ 
pi@raspberrypi:~ $ ifconfig eth0 | grep "inet 192" | cut -c 14-25
192.168.2.24
pi@raspberrypi:~ $ 
pi@raspberrypi:~ $ 

これで、pythonに移動して次のことができます。

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