web-dev-qa-db-ja.com

Pythonのstdlibを使ってローカルIPアドレスを見つける

標準のライブラリのみを使用して、PythonプラットフォームでローカルIPアドレス(192.168.x.xまたは10.0.x.x)をどのように見つけることができますか?

473
UnkwnTech
import socket
socket.gethostbyname(socket.gethostname())

これは常にうまくいくとは限りません(127.0.0.1内のホスト名を/etc/hostsとして持つマシンでは127.0.0.1を返します)。gimelが示すように、気まぐれな作業になります。代わりにsocket.getfqdn()を使用してください。もちろんあなたのマシンは解決可能なホスト名を必要とします。

389
Vinko Vrsalovic

私はちょうどこれを見つけたが、それは少し厄介に思えます、しかし彼らは* 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()

これはあなたがインターネットにアクセスできること、そしてローカルプロキシがないことを前提としています。

398
UnkwnTech

このメソッドはローカルボックス上の "プライマリ" 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などを含む)に接続する必要がある場合は、 この回答 を参照してください。

自宅のWi-FiボックスのようにNATファイアウォールの内側にいる場合は、一般のNAT IPではなく、プライベートのNAT IPが表示されます。ローカルWIFIルーターへのデフォルトルートを持つローカルネットワーク。 wifiルーターの外部IPを取得するには、これをこのボックスで実行するか、whatismyip.com/whatismyipaddress.comなど、IPを反映する可能性のある外部サービスに接続する必要がありますが、元の質問とはまったく異なります。 :)

コメントでのPedroの提案によるconnect()呼び出しを更新。 (特定の使用許諾契約書が必要な場合、これはパブリックドメイン/任意の用途に無料、またはお客様の選択によるStack Overflowのコード/コンテンツライセンスごとのMIT/CC2-BY-SAです。)

151
Jamieson Becker

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])'"
  • 現在のIPv4アドレスを見つけるために、Python 2.x、Python 3.x、最近および古いLinuxディストリビューション、OSX/macOS、およびWindowsで正しく動作します。
  • 複数の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アドレスが設定されていない場合、これは例外をスローします。

インターネットに接続していないLANでも動作するバージョン:

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())を使ってもここではうまくいきませんでした。私が使っていたコンピューターの1つに、重複するエントリとそれ自身への参照がある/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])

これは、LinuxとWindows上のPython 2と3で動作しますが、いくつかのネットワークデバイスやIPv6を扱いません。しかし、最近のLinuxディストリビューションでは動作しなくなったので、代わりにこの代替手法を試しました。それはポート8.8.8.853でGoogle DNSサーバーに接続しようとします:

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

それから私は上記の2つのテクニックをどこでも使えるはずのワンライナーに結合し、そしてこの答えの一番上にmyipエイリアスとPythonスニペットを作成しました。

IPv6の人気が高まり、複数のネットワークインターフェイスを持つサーバーでは、IPアドレスを見つけるためにサードパーティ製のPythonモジュールを使用する方が、ここに記載されている方法よりも堅牢で信頼性が高いと考えられます。

137
Alexander

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で動作するはずだと主張しています。

85
DzinX

ソケットAPIメソッド

https://stackoverflow.com/a/28950776/711085 を参照してください。

欠点:

  • クロスプラットフォームではありません
  • インターネット上の特定のアドレスの存在に関連した、より多くのフォールバックコードが必要です。
  • あなたがNATの後ろにいるならば、これはまた働かないでしょう
  • おそらく(通常はISPの)DNSの可用性とは無関係ではなく、UDP接続を作成します(8.8.8.8を使用するなどのアイデアについては他の回答を参照してください:Googleの(偶然にもDNS)サーバー)
  • 未使用であることが仕様保証されている数値IPアドレスのように、宛先アドレスを必ずUNREACHABLEにしてください。 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)

利点:

  • この方法の1つの利点はクロスプラットフォームです。
  • それは醜いNAT(例えばあなたのホームルータ)の後ろから動作します。

デメリット(および回避策):

  • このWebサイトを立ち上げ、フォーマットを変更しない(ほぼ確実に変更しない)こと、およびDNSサーバーが機能していることが必要です。障害が発生した場合に他のサードパーティIPアドレスリフレクタにも問い合わせることで、この問題を軽減できます。
  • 複数のリフレクタを照会しない(自分のアドレスが間違っていることを知らせることを防ぐために)、またはHTTPSを使用しない(man-in-the-middle攻撃を防ぐため)サーバーになる)

edit:最初はこれらの方法は本当に悪いと思っていましたが(多くのフォールバックを使わない限り、コードは今から何年も無関係かもしれません)、それは「インターネットとは何ですか」という質問を投げかけます。コンピュータには、さまざまなネットワークを指す多数のインタフェースがあります。このトピックに関するより詳細な説明については、google for gateways and routesを参照してください。コンピュータは、内部ゲートウェイを介して内部ネットワークにアクセスすること、または例えばルータ上のゲートウェイを介してワールドワイドウェブにアクセスすることが可能であり得る(通常そうである)。 OPが要求するローカルIPアドレスは単一のリンク層に関して明確に定義されているだけなので、それを指定する必要があります(「ネットワークカードなのか、それともイーサネットケーブルなのか」。 。提起されたように、この質問に対して複数の非固有の回答があるかもしれません。しかし、ワールドワイドウェブ上のグローバルIPアドレスはおそらく(明確なネットワーク断片化がない限り)明確に定義されています:おそらくTLDにアクセスできるゲートウェイ経由のリターンパスです。

48
ninjagecko

コンピュータにインターネットへのルートがある場合、/ etc/hostsが正しく設定されていなくても、これは always が優先ローカル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]
41
Collin Anderson

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'
>>> 
38
tMC

次のモジュールを使用して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

単一のIPv4ベースのLAN内にあるシステムでの使用を意図したwindowsとlinuxでテストされています(そしてそれらのために追加のモジュールを必要としません)。

Alexander で指摘されているように、インターフェース名の固定リストは、予測可能なインターフェース名に関してsystemd v197の変更を採用した最近のLinuxバージョンでは機能しません。そのような場合は、リストをシステム上のインタフェース名に手動で置き換えるか、 netifaces のような別の解決策を使用する必要があります。

26
smerlin

私は私のUbuntuマシンでこれを使用します。

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

これはうまくいきません。

24
shino

外部のパッケージを使いたくないし、外部のインターネットサーバーに頼りたくないのなら、これは役に立つかもしれません。これは 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上でのみ機能します。

19
DzinX

私はそれを信じていないバージョンがまだ投稿されています。私はUbuntu 12.04でpython 2.7を使ってテストしました。

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'
17
Graham Chap

Debian(テスト済み)と私はほとんどのLinuxを疑っています。

import commands

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

MS Windows上(テスト済み)

import socket

socket.gethostbyname(socket.gethostname())
16
www-0av-Com

Ninjageckoの答えのバリエーション。これは、UDPブロードキャストを許可し、LANまたはインターネット上のアドレスへのアクセスを必要としないLANであれば機能します。

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

コマンドライン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アドレスが表示されます。

8
viker

プラットフォームに依存しない、他のコンピュータに接続してIPアドレスを送信する以外に、これを実行する方法はありません。例えば、 findmyipaddress です。接続しているコンピュータがNATの後ろにある場合を除き、NATの後ろにあるIPアドレスが必要な場合、これは機能しません。

これはLinuxで動く1つの解決策です: ネットワークインターフェースに関連したIPアドレスを取得します

8
Jason Baker

これはUnkwnTechの答えの変種です - それはホストのプライマリLAN IPアドレスを返すget_local_addr()関数を提供します。 ipv6のサポート、エラー処理、localhost/linklocalアドレスの無視、そして接続にTESTNETアドレス(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
7
Eli Collins

参考までに私はその方法を検証することができます:

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

OS X(10.6、10.5)、Windows XP、および適切に管理されたRHEL部門サーバーで動作します。非常に小さなCentOS VM上ではうまくいきませんでした。カーネルハッキングをしているだけです。そのため、その場合は127.0.0.1アドレスを確認し、その場合は次のようにします。

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

その後、出力からIPアドレスを解析します。 ifconfigは、デフォルトでは通常のユーザーのPATHには含まれていないため、コマンドでフルパスを指定するのはそのためです。これが役に立つことを願っています。

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

これはほとんどの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()
6
fccoelho

socket.gethostbyname(socket.gethostname())も127.0.0.1を返したので、この答えは私の個人的なLAN IP取得の問題を解決する試みです。この方法はインターネットだけでLAN接続を必要としません。コードは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 __== '__main__':
    print(get_local_ip())
5
WolfRage

127.0.1.1あなたの本当のIPアドレスです。より一般的に言えば、コンピュータは任意の数のIPアドレスを持つことができます。プライベートネットワーク - 127.0.0.0/8、10.0.0.0.0/8、172.16.0.0/12、192.168.0.0/16 - に対してそれらをフィルタリングできます。

ただし、すべてのIPアドレスを取得するためのクロスプラットフォームな方法はありません。 Linuxでは、 SIOCGIFCONF ioctlを使用できます。

4
phihag

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)]
4
Ben Last

さてあなたはあなたの現在のIPアドレスを知るためにGNU/Linux上でコマンド "ip route"を使うことができます。

これはルータ/モデムで動作しているDHCPサーバによってインターフェイスに与えられたIPを示しています。通常、「192.168.1.1/24」はローカルネットワークのIPです。「24」は、DHCPサーバーがマスク範囲内で指定したIPアドレスの範囲を意味します。

ここに例があります: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()    

これの利点は、ネットワークインターフェースを指定する必要がないということです。ソケットサーバーを実行しているとき、それはかなり役に立ちます

Easy_installあるいはPipを使ってPyNotifyをインストールすることができます。

easy_install py-notify

または

pip install py-notify

またはPythonスクリプト/インタプリタ内

from pip import main

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

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ルールをその場で生成するのに便利です)。それで、これは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]

そして、いいえ、私はリスト内包表記には興味がありません。最近の私の脳の働きはまさにその通りです。

次のスニペットはそれをすべて印刷します。

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)

楽しい!

3
user3712955

注:これは標準ライブラリを使用していませんが、非常に単純です。

$ pip install pif

from pif import get_public_ip
get_public_ip()
3
import netifaces as ni 

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

これにより、UbuntuシステムとMacOSのIPアドレスが返されます。出力は私のIPのようにシステムのIPアドレスになります:192.168.1.10。

3
Ishwarya

あなたがあなたのlocalhostのIPアドレス127.0.0.1とは異なるIPV4アドレスを探しているなら、これは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アドレスを与えます。

3
hmofrad

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()
3
RiccardoCh
import socket
socket.gethostbyname(socket.getfqdn())
2
Oink

私は「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

私はこれが質問に直接答えないことを知っています、しかしこれは関連する質問を解決しようとしている人、そして同じ思考の列をたどっていた人には役立つはずです。これには、クロスプラットフォームソリューションであるという利点があります(私は思います)。

2
Etienne Perot

* nixシステム上のIPアドレスのリストについては、

import subprocess
co = subprocess.Popen(['ifconfig'], stdout = subprocess.PIPE)
ifconfig = co.stdout.read()
ip_regex = re.compile('((25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-4]|2[0-5][0-9]|[01]?[0-9][0-9]?))')
[match[0] for match in ip_regex.findall(ifconfig, re.MULTILINE)]

この回答には少し時間がかかりますが、他の人が役に立つと思うかもしれません:-)

シモンズ:それは同様にブロードキャストアドレスとネットマスクを返すでしょう。

1
Kulbir Saini

これはあまりPythonicではありませんが、Windows上で確実に機能します。

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

print getWinIP()

ええ、それはハックです、しかし時々私はオペレーティングシステムを二次的に推測する気がしないで、先に進んで、そして内蔵されて動くものを使うだけです。

1
LRund

新しく導入されたasyncioパッケージを利用したPython 3.4バージョン。

async get_local_ip():
    loop = asyncio.get_event_loop()
    transport, protocol = await loop.create_datagram_endpoint(
        asyncio.DatagramProtocol,
        remote_addr=('8.8.8.8', 80))
    result = transport.get_extra_info('sockname')[0])
    transport.close()
    return result

これはUnkwnTechの 優れた答え に基づいています。

1
Frederik Aalund

さて、これはWindows特有のもので、 python WMIモジュール のインストールが必要です。これはもう1つの選択肢です。すでに優れたものが多数ありますが、プロジェクトには適しているかもしれません。

Import WMI

def getlocalip():
    local = wmi.WMI()
    for interface in local.Win32_NetworkAdapterConfiguration(IPEnabled=1):
        for ip_address in interface.IPAddress:
            if ip_address != '0.0.0.0':
                localip = ip_address
    return localip







>>>getlocalip()
u'xxx.xxx.xxx.xxx'
>>>

ちなみに、WMIは非常に強力です...ウィンドウマシンのリモート管理をしているのなら、絶対にそれができることを確認してください。

1
snakebarber
from netifaces import interfaces, ifaddresses, AF_INET
iplist = [ifaddresses(face)[AF_INET][0]["addr"] for face in interfaces() if AF_INET in ifaddresses(face)]
print(iplist)
['10.8.0.2', '192.168.1.10', '127.0.0.1']
0
Villiam

マシンは、あなたが言及した複数のネットワークインターフェース(ローカルループバック127.0.0.1を含む)を持つことができます。 OSに関する限り、それはまた「本当のIPアドレス」です。

すべてのインターフェースを追跡したい場合は、次のPuthonパッケージを見てください。 http://alastairs-place.net/netifaces/ /

Hostsファイルからloopbackエントリを省略すると、gethostbynameが127.0.0.1を返さないようにできます。 (検証予定).

0
ddewaele

以前の回答に対するさらに別の変形は、my-ip-toという名前の実行可能スクリプトに保存することができます。

#!/usr/bin/env python

import sys, socket

if len(sys.argv) > 1:
    for remote_Host in sys.argv[1:]:
        # determine local Host ip by outgoing test to another Host
        # use port 9 (discard protocol - RFC 863) over UDP4
        with socket.socket(socket.AF_INET, socket.SOCK_DGRAM) as s:
            s.connect((remote_Host, 9))
            my_ip = s.getsockname()[0]
            print(my_ip, flush=True)
else:
    import platform

    my_name = platform.node()
    my_ip = socket.gethostbyname(my_name)
    print(my_ip)

それは任意の数のリモートホストを取り、それらに一つずつ到達するためにローカルIPアドレスをプリントアウトします。

$ my-ip-to z.cn g.cn localhost
192.168.11.102
192.168.11.102
127.0.0.1
$

引数が指定されていない場合は、最善策を印刷してください。

$ my-ip-to
192.168.11.102
0
Compl Yue

Linuxの場合、check_outputシステムコマンドのhostname -Iを次のように使用できます。

from subprocess import check_output
check_output(['hostname', '-I'])

シンプルだけど甘い!

def getip():

    import socket
    hostname= socket.gethostname()
    ip=socket.gethostbyname(hostname)

    return(ip)
0
Matt

これは以前に投稿された回答と非常によく似ていますが、私はこの通話の使い方では見つけることができませんでした。これは私がipv4に使っているものです。 ipv6の場合は「。」を変更します。 「:」に

import socket
print next(i[4][0] for i in socket.getaddrinfo(
    socket.gethostname(), 80) if '127.' not in i[4][0] and '.' in i[4][0]);"
0
Wyrmwood

Linux環境では、/ proc/net/tcpを読むと、2番目(localaddress)と3番目(remoteaddress)にIPアドレスが16進数で表示されます。

ヒント:2番目の列がゼロに設定されている場合(00000000:0000)、リスンポート:)

https://github.com/romol0s/python/blob/master/general/functions/getTcpListenIpsByPort.py

https://www.kernel.org/doc/Documentation/networking/proc_net_tcp.txt

0
Romolo