当Unix上的Python脚本发生错误时,会发送一封电子邮件。
如果IP地址是测试服务器的192.168.100.37,我被要求将{Testing Environment}添加到电子邮件的主题行。通过这种方式,我们可以拥有一个版本的脚本,以及一种判断电子邮件是否来自测试服务器上的混乱数据的方法。
然而,当我谷歌时,我一直在寻找这段代码:
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,但不管怎么说都不是我想要的。当我谷歌时,我不断使用相同的语法,Bash脚本或netifaces,我正在尝试使用标准库。
那么如何在Python中获取eth0的IP地址呢?
答案 0 :(得分:147)
两种方法:
您需要询问绑定到eth0
接口的IP地址。这可以从netifaces package
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()
这是一种在不使用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
答案 1 :(得分:96)
或者,如果您想获取用于连接到网络的任何接口的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的路由来使用它。它所做的就是打开一个套接字,但不发送任何数据。
答案 2 :(得分:25)
为接口返回带有ip-addresses的字符串的简单方法是:
from subprocess import check_output
ips = check_output(['hostname', '--all-ip-addresses'])
有关详细信息,请参阅hostname。
答案 3 :(得分:16)
如果您只需要在Unix上工作,则可以使用系统调用(参见Stack Overflow问题 Parse ifconfig to get only my IP address using Bash ):
import os
f = os.popen('ifconfig eth0 | grep "inet\ addr" | cut -d: -f2 | cut -d" " -f1')
your_ip=f.read()
答案 4 :(得分:15)
由于大多数答案使用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()
或者,您可以使用split()
而不是grep和awk将部分解析任务转移到python解释器,正如@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()
调用返回的数组的边界。
使用正则表达式的另一个版本:
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]
答案 5 :(得分:2)
尝试以下代码,它适用于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
答案 6 :(得分:1)
以@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]
答案 7 :(得分:0)
它对我有用
contourSizes()
答案 8 :(得分:0)
在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
答案 9 :(得分:0)
这是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)
答案 10 :(得分:0)
还有另一种使用Python从NIC获取IP地址的方法。
我把它作为我很久以前开发的应用程序的一部分,我不想简单地git rm script.py
。因此,在这里,我提供了使用subprocess
的方法,并出于功能性方法和更少的代码行而列出了理解:
import subprocess as sp
__version__ = "v1.0"
__author__ = "@ivanleoncz"
def get_nic_ipv4(nic):
"""
Get IP address from a NIC.
Parameter
---------
nic : str
Network Interface Card used for the query.
Returns
-------
ipaddr : str
Ipaddress from the NIC provided as parameter.
"""
result = None
try:
result = sp.check_output(["ip", "-4", "addr", "show", nic],
stderr=sp.STDOUT)
except Exception:
return "Unkown NIC: %s" % nic
result = result.decode().splitlines()
ipaddr = [l.split()[1].split('/')[0] for l in result if "inet" in l]
return ipaddr[0]
此外,您可以使用类似的方法来获取NIC列表:
def get_nics():
"""
Get all NICs from the Operating System.
Returns
-------
nics : list
All Network Interface Cards.
"""
result = sp.check_output(["ip", "addr", "show"])
result = result.decode().splitlines()
nics = [l.split()[1].strip(':') for l in result if l[0].isdigit()]
return nics
这是Gist的解决方案。
您将遇到类似这样的内容:
$ python3
Python 3.6.7 (default, Oct 22 2018, 11:32:17)
[GCC 8.2.0] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>>
>>>
>>> import helpers
>>>
>>> helpers.get_nics()
['lo', 'enp1s0', 'wlp2s0', 'docker0']
>>> helpers.get_nic_ipv4('docker0')
'172.17.0.1'
>>> helpers.get_nic_ipv4('docker2')
'Unkown NIC: docker2'
答案 11 :(得分:0)
这将收集主机上的所有IP,并过滤掉环回/本地链接和IPv6。还可以对其进行编辑,以仅允许使用IPv6,或者仅允许使用IPv4和IPv6,以及允许在IP列表中使用回送/本地链接。
from socket import getaddrinfo, gethostname
import ipaddress
def get_ip(ip_addr_proto="ipv4", ignore_local_ips=True):
# By default, this method only returns non-local IPv4 Addresses
# To return IPv6 only, call get_ip('ipv6')
# To return both IPv4 and IPv6, call get_ip('both')
# To return local IPs, call get_ip(None, False)
# Can combime options like so get_ip('both', False)
af_inet = 2
if ip_addr_proto == "ipv6":
af_inet = 30
elif ip_addr_proto == "both":
af_inet = 0
system_ip_list = getaddrinfo(gethostname(), None, af_inet, 1, 0)
ip_list = []
for ip in system_ip_list:
ip = ip[4][0]
try:
ipaddress.ip_address(str(ip))
ip_address_valid = True
except ValueError:
ip_address_valid = False
else:
if ipaddress.ip_address(ip).is_loopback and ignore_local_ips or ipaddress.ip_address(ip).is_link_local and ignore_local_ips:
pass
elif ip_address_valid:
ip_list.append(ip)
return ip_list
print(f"Your IP Address is: {get_ip()}")
返回您的IP地址为:['192.168.1.118']
如果我运行get_ip('both',False),它将返回
您的IP地址为:[':: 1','fe80 :: 1','127.0.0.1','192.168.1.118','fe80 :: cb9:d2dd:a505:423a']
答案 12 :(得分:-1)
试试这个:
将 netifaces 导入为 ni
def test_netowrk(): 接口 = ni.interfaces()
for i in interfaces: #will cycle through all available interfaces and check each one. you can use anything for "i". its almost like saying import netifaces as ni. but i doesn't need to be declared, the systems assumes that for (what you put here) in interfaces means what you put there should resemble each of the results returned are represented by i.
if i != "lo": #lo is the local loopback. This will remove lo from the interfaces it checks.
try:
ni.ifaddresses(i)
gws = ni.gateways()
gateway = gws['default'][ni.AF_INET][0]
ip = ni.ifaddresses(i)[ni.AF_INET][0]['addr']
sm = ni.ifaddresses(i)[ni.AF_INET][0]['netmask']
print ("Network information for " + i + ":")
print ("IP: " + ip)
print ("Subnet Mask: " + sm)
print ("Gateway: " + gateway)
print ()
except: #this is good to have in case you have a disconnected wifi or trying to test a network with no DHCP
print (i + " is not connected or DHCP is not available. Try setting a static IP.")
test_netowrk()
结果:
eth0 的网络信息:
IP:192.168.1.172
子网掩码:255.255.255.0
网关:192.168.1.254
wlan0 未连接或 DHCP 不可用。