如何在 Python 中从 NIC 获取 IP 地址?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/24196932/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How can I get the IP address from NIC in Python?
提问by Memor-X
When an error occurs in a Python script on Unix , an email is sent.
当 Unix 上的 Python 脚本发生错误时,会发送一封电子邮件。
I have been asked to add {Testing Environment} to the subject line of the email if the IP address is 192.168.100.37 which is the testing server. This way we can have one version of a script and a way to tell if the email is coming from messed up data on the testing server.
如果 IP 地址是测试服务器 192.168.100.37,我被要求在电子邮件的主题行中添加 {Testing Environment}。通过这种方式,我们可以拥有一个版本的脚本和一种方法来判断电子邮件是否来自测试服务器上的混乱数据。
However, when I google I keep finding this code:
但是,当我用谷歌搜索时,我一直在寻找这个代码:
import socket
socket.gethostbyname(socket.gethostname())
However, that's giving me the IP address of 127.0.1.1. When I use ifconfig
I get this
但是,这给了我 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)
Firstly, I don't know where it got 127.0.1.1 from, but either way that's not what I want. When I google I keep coming to the same syntax, Bashscripts or netifaces and I'm trying to use standard libraries.
首先,我不知道它从哪里得到 127.0.1.1,但无论哪种方式,这都不是我想要的。当我使用谷歌搜索时,我一直在使用相同的语法、Bash脚本或 netifaces,并且我正在尝试使用标准库。
So how can I get the IP address of eth0 in Python?
那么如何在Python中获取eth0的IP地址呢?
采纳答案by Martin Konecny
Two methods:
两种方法:
Method #1 (use external package)
方法#1(使用外部包)
You need to ask for the IP address that is bound to your eth0
interface. This is available from the netifaces package
您需要询问绑定到您的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"
You can also get a list of all available interfaces via
您还可以通过以下方式获取所有可用接口的列表
ni.interfaces()
Method #2 (no external package)
方法#2(无外部包)
Here's a way to get the IP address without using a python package:
这是一种无需使用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'
Note: detecting the IP address to determine what environment you are using is quite a hack. Almost all frameworks provide a very simple way to set/modify an environment variable to indicate the current environment. Try and take a look at your documentation for this. It should be as simple as doing
注意:通过检测 IP 地址来确定您正在使用的环境是一个非常棘手的问题。几乎所有框架都提供了一种非常简单的方法来设置/修改环境变量以指示当前环境。尝试查看您的文档。它应该像做一样简单
if app.config['ENV'] == 'production':
#send production email
else:
#send development email
回答by jeremyjjbrown
Alternatively, if you want to get the IP address of whichever interface is used to connect to the network without having to know its name, you can use this:
或者,如果您想获取用于连接到网络的任何接口的 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]
I know it's a little different than your question, but others may arrive here and find this one more useful. You do not have to have a route to 8.8.8.8 to use this. All it is doing is opening a socket, but not sending any data.
我知道这与您的问题略有不同,但其他人可能会到达这里并发现这个问题更有用。您不必有到 8.8.8.8 的路由来使用它。它所做的只是打开一个套接字,但不发送任何数据。
回答by olmerg
If you only need to work on Unix, you can use a system call (ref. Stack Overflow question Parse ifconfig to get only my IP address using Bash):
如果您只需要在 Unix 上工作,您可以使用系统调用(参考 Stack Overflow question 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()
回答by xiaoweiz
try below code, it works for me in Mac10.10.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
回答by Abhijit
It worked for me
它对我有用
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
回答by Giles Greenway
Find the IP address of the first eth/wlan entry in ifconfig that's RUNNING:
在正在运行的 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
回答by Ivan De Paz Centeno
Since most of the answers use ifconfig
to extract the IPv4 from the eth0 interface, which is deprecated in favor of ip addr
, the following code could be used instead:
由于大多数答案都用于ifconfig
从 eth0 接口中提取 IPv4,该接口已被弃用,ip addr
因此可以使用以下代码:
import os
ipv4 = os.popen('ip addr show eth0 | grep "\<inet\>" | awk \'{ print }\' | awk -F "/" \'{ print }\'').read().strip()
ipv6 = os.popen('ip addr show eth0 | grep "\<inet6\>" | awk \'{ print }\' | awk -F "/" \'{ print }\'').read().strip()
UPDATE:
更新:
Alternatively, you can shift part of the parsing task to the python interpreter by using split()
instead of grep and awk, as @serg points out in the comment:
或者,您可以使用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]
But in this case you have to check the bounds of the array returned by each split()
call.
但在这种情况下,您必须检查每次split()
调用返回的数组的边界。
UPDATE 2:
更新 2:
Another version using regex:
使用正则表达式的另一个版本:
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]
回答by Alexander
回答by Steve Cohen
Building on the answer from @jeremyjjbrown, another version that cleans up after itself as mentioned in the comments to his answer. This version also allows providing a different server address for use on private internal networks, etc..
以@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]
回答by Omar Cruz
This is the result of ifconfig:
这是 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:~ $
Cutting a bit the output, we have:
减少一点输出,我们有:
pi@raspberrypi:~ $
pi@raspberrypi:~ $ ifconfig eth0 | grep "inet 192" | cut -c 14-25
192.168.2.24
pi@raspberrypi:~ $
pi@raspberrypi:~ $
Now, we can go to python and do:
现在,我们可以转到 python 并执行以下操作:
import os
mine = os.popen('ifconfig eth0 | grep "inet 192" | cut -c 14-25')
myip = mine.read()
print (myip)