问题
When an error occurs in a Python script on Unix , an email is sent.
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.
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
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, Bash scripts or netifaces and I\'m trying to use standard libraries.
So how can I get the IP address of eth0 in Python?
回答1:
Two methods:
Method #1 (use external package)
You need to ask for the IP address that is bound to your eth0
interface. This is available from the 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"
You can also get a list of all available interfaces via
ni.interfaces()
Method #2 (no external package)
Here's a way to get the IP address without using a python package:
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
if app.config['ENV'] == 'production':
#send production email
else:
#send development email
回答2:
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:
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.
回答3:
A simple approach which returns a string with ip-addresses for the interfaces is:
from subprocess import check_output
ips = check_output(['hostname', '--all-ip-addresses'])
for more info see hostname.
回答4:
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):
import os
f = os.popen('ifconfig eth0 | grep "inet\ addr" | cut -d: -f2 | cut -d" " -f1')
your_ip=f.read()
回答5:
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:
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()
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:
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.
UPDATE 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]
回答6:
try below code, it works for me in 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
回答7:
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..
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]
回答8:
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
回答9:
Find the IP address of the first eth/wlan entry in ifconfig that's RUNNING:
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
回答10:
This is the result of 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:
import os
mine = os.popen('ifconfig eth0 | grep "inet 192" | cut -c 14-25')
myip = mine.read()
print (myip)
回答11:
Yet another way of obtaining the IP Address from a NIC, using Python.
I had this as part of an app that I developed long time ago, and I didn't wanted to simply git rm script.py
. So, here I provide the approach, using subprocess
and list comprehensions for the sake of functional approach and less lines of code:
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]
Additionally, you can use a similar approach for obtaining a list of NICs:
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
Here's the solution as a Gist.
And you would have something like this:
$ 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'
来源:https://stackoverflow.com/questions/24196932/how-can-i-get-the-ip-address-from-nic-in-python