Pythonのstdlibを使用してローカルIPアドレスを見つける
-
03-07-2019 - |
質問
PythonプラットフォームでローカルIPアドレス(つまり、192.168.x.xまたは10.0.x.x)を個別に検索し、標準ライブラリのみを使用するにはどうすればよいですか?
解決
import socket
socket.gethostbyname(socket.gethostname())
これは常に機能しません( 127.0.0.1
として / etc / hosts
にホスト名があるマシンでは 127.0.0.1
を返します) 、緩和はgimelが示すものになります。代わりに socket.getfqdn()
を使用してください。もちろん、マシンには解決可能なホスト名が必要です。
他のヒント
これを見つけたばかりですが、少しハックがかかっているように見えますが、彼らは* 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()
これは、インターネットにアクセスでき、ローカルプロキシがないことを前提としています。
このメソッドは、「プライマリ」を返します。ローカルボックス(デフォルトルートのあるもの)の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を返します。代わりに、すべてのインターフェース(localhostなどを含む)に接続されたすべてのIPが必要な場合は、この回答。
自宅のWi-FiボックスなどのNATファイアウォールの背後にいる場合、パブリックNAT IPは表示されませんが、ローカルWIFIルーターへのデフォルトルートがあるローカルネットワーク上のプライベートNAT IPが表示されます。 Wi-Fiルーターの外部IPを取得するには、THATボックスでこれを実行するか、IPを反映できるwhatismyip.com/whatismyipaddress.comなどの外部サービスに接続する必要がありますが、元の質問とはまったく異なります。 :)
コメントでのPedroの提案ごとに、connect()呼び出しを更新しました。 (特定のライセンスステートメントが必要な場合、これはパブリックドメイン/任意の使用無料、またはオプションでStack Overflowのコード/コンテンツライセンスごとにMIT / CC2-BY-SAです。)
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アドレスが設定されていない場合、これは例外をスローします。
インターネットに接続していない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ディストリビューションでは動作しなくなったため、代わりにこの代替手法を試しました。ポート 53
の 8.8.8.8
で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つの手法を組み合わせて、どこでも動作する1つのライナーを作成し、この回答の先頭に myip
エイリアスとPythonスニペットを作成しました。
IPv6の人気が高まり、複数のネットワークインターフェイスを備えたサーバーの場合、IPアドレスを見つけるためにサードパーティのPythonモジュールを使用することは、おそらくここに挙げたどの方法よりも堅牢で信頼性があります。
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で動作するはずだと主張しています。
ソケットAPIメソッド
https://stackoverflow.com/a/28950776/711085
を参照欠点:
- クロスプラットフォームではありません。
- インターネット上の特定のアドレスの存在に関連付けられた、より多くのフォールバックコードが必要です
- これは、NATの背後にいる場合も機能しません
- (通常はISPの)DNSの可用性に依存せずに、おそらくUDP接続を作成します(8.8.8.8を使用するなどのアイデアについては、他の回答を参照してください:Google(偶然にもDNS)サーバー)
- 未使用であることが保証されている数値のIPアドレスのように、宛先アドレスをUNREACHABLEにしてください。 fakesubdomain.google.comやsomefakewebsite.comなどのドメインを使用しないでください。そのパーティーを(現在または将来)スパムし、その過程で自分のネットワークボックスもスパムすることになります。
リフレクター方式
(これはローカルIPアドレス、たとえば192.168 ...のOPの質問には答えないことに注意してください。これは、ユースケースによっては望ましいパブリック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つは、クロスプラットフォームである
- ItいNAT(たとえば、ホームルーター)の背後から動作します。
欠点(および回避策):
- このWebサイトが稼働していること、フォーマットが変わらないこと(ほぼ間違いなく変わらないこと)、およびDNSサーバーが機能していることが必要です。障害が発生した場合に他のサードパーティのIPアドレスリフレクターを照会することにより、この問題を軽減できます。
- 複数のリフレクターをクエリしない場合(攻撃されたリフレクターが自分のアドレスがそうではないことを知らせるのを防ぐため)、またはHTTPSを使用しない場合(man-in-the-サーバーを装った中間攻撃)
編集:最初はこれらの方法は本当に悪いと思っていましたが(多くのフォールバックを使用しない限り、コードは何年も後から無関係になる可能性があります) ?&quot;。コンピューターには、多くの異なるネットワークを指す多くのインターフェイスがあります。トピックの詳細な説明については、Googleで gateways and routes
をご覧ください。コンピューターは、内部ゲートウェイを介して内部ネットワークにアクセスしたり、ルーターなどのゲートウェイを介してWorld Wide Webにアクセスしたりすることができます(通常の場合)。 OPが要求するローカルIPアドレスは、単一のリンク層に関してのみ明確に定義されているため、それを指定する必要があります(「ネットワークカードですか、それともイーサネットケーブルですか?」 ;)。提起されているように、この質問に対する複数の一意でない回答があるかもしれません。ただし、World Wide WebのグローバルIPアドレスはおそらく(大規模なネットワークの断片化がない場合)明確に定義されています。おそらく、TLDにアクセスできるゲートウェイを経由するリターンパスです。
コンピューターにインターネットへのルートがある場合、/ 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]
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'
>>>
次のモジュールを使用して:
#!/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ベースのLANにあるシステムでの使用を目的としています。
Alexander 。 このような場合、リストをシステム上のインターフェイス名に手動で置き換えるか、のような別のソリューションを使用する必要があります。 netifaces 。
ubuntuマシンでこれを使用します:
import commands
commands.getoutput("/sbin/ifconfig").split("\n")[1].split()[1][5:]
これは機能しません。
外部パッケージを使用したくない場合、および外部インターネットサーバーに依存したくない場合、これが役立つ場合があります。 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でのみ機能します。
まだ投稿されていないバージョン。 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'
Debian(テスト済み)で、ほとんどのLinuxが疑われます。
import commands
RetMyIP = commands.getoutput("hostname -I")
MS Windowsで(テスト済み)
import socket
socket.gethostbyname(socket.gethostname())
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())
別のコンピュータに接続してIPアドレスを送信する以外に、プラットフォームに依存しないこれを行う方法はありません。例: findmyipaddress 。接続先のコンピューターもNATの背後にない限り、NATの背後にあるIPアドレスが必要な場合、これは機能しないことに注意してください。
Linuxで動作する1つのソリューションは次のとおりです。ネットワークインターフェイスに関連付けられたIPアドレスを取得 。
&quot; clean&quot;を生成する1つの簡単な方法コマンドラインユーティリティ経由の出力:
import commands
ips = commands.getoutput("/sbin/ifconfig | grep -i \"inet\" | grep -iv \"inet6\" | " +
"awk {'print $2'} | sed -ne 's/addr\:/ /p'")
print ips
システム上のすべてのIPv4アドレスが表示されます。
FYIメソッドを検証できます:
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にないため、コマンドでフルパスを指定することに注意してください。これがお役に立てば幸いです。
これはUnkwnTechの回答の変形です。ホストのプライマリLAN IPアドレスを返す get_local_addr()
関数を提供します。これにより、ipv6サポート、エラー処理、localhost / linklocal addrsの無視、および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
これはほとんどの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()
import socket
[i[4][0] for i in socket.getaddrinfo(socket.gethostname(), None)]
この答えは、 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 __name__ == '__main__':
print(get_local_ip())
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を使用できます。
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)]
さて、コマンド「ip route」を使用できます。 GNU / Linuxで現在のIPアドレスを確認します。
これは、ルーター/モデムで実行されているDHCPサーバーによってインターフェイスに与えられたIPを示します。通常「192.168.1.1/24」; 「24」がローカルネットワークのIPです。は、マスク範囲内の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 script / interpreter内
from pip import main
main(['install', 'py-notify'])
注:これは標準ライブラリを使用していませんが、非常に簡単です。
$ pip install pif
from pif import get_public_ip
get_public_ip()
netifacesは、pipおよびeasy_installを介して利用できます。 (ベースにはないが、インストールする価値があるかもしれない。)
netifacesには、プラットフォーム間でいくつかの奇妙な点があります:
- localhost / loopbackインターフェースが常に含まれているとは限りません(Cygwin)。
- アドレスはプロトコルごと(IPv4、IPv6など)にリストされ、プロトコルはインターフェイスごとにリストされます。一部のシステム(Linux)では、各プロトコルとインターフェースのペアに独自の関連インターフェース(interface_name:n表記を使用)がありますが、他のシステム(Windows)では、単一のインターフェースに各プロトコルのアドレスのリストがあります。どちらの場合もプロトコルリストがありますが、1つの要素しか含まれていない可能性があります。
ここで遊ぶ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)
お楽しみください
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()
import netifaces as ni
ni.ifaddresses('eth0')
ip = ni.ifaddresses('eth0')[ni.AF_INET][0]['addr']
print(ip)
これにより、UbuntuシステムとMacOSのIPアドレスが返されます。出力は、私のIP:192.168.1.10。のようなシステムIPアドレスになります。
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]
1行で記述することもできます:
address = subprocess.check_output(['hostname', '-s', '-I']).decode('utf-8')[:-1]
/ etc / hostname
に localhost
を配置しても、コードはローカルIPアドレスを提供します。
「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
これは質問に直接答えないことは知っていますが、これは関連する質問を解決しようとする人や、同じ考えの列に従っている人にとって役立つはずです。これには、クロスプラットフォームソリューションであるという利点があります(私は思う)。