##// END OF EJS Templates
use netifaces for faster IPython.utils.localinterfaces
MinRK -
Show More
@@ -5,6 +5,8 b' LOCALHOST : The loopback interface, or the first interface that points to this'
5 machine. It will *almost* always be '127.0.0.1'
5 machine. It will *almost* always be '127.0.0.1'
6
6
7 LOCAL_IPS : A list of IP addresses, loopback first, that point to this machine.
7 LOCAL_IPS : A list of IP addresses, loopback first, that point to this machine.
8 This will include LOCALHOST, PUBLIC_IPS, and aliases for all hosts,
9 such as '0.0.0.0'.
8
10
9 PUBLIC_IPS : A list of public IP addresses that point to this machine.
11 PUBLIC_IPS : A list of public IP addresses that point to this machine.
10 Use these to tell remote clients where to find you.
12 Use these to tell remote clients where to find you.
@@ -31,7 +33,7 b' from .data import uniq_stable'
31 LOCAL_IPS = []
33 LOCAL_IPS = []
32 PUBLIC_IPS = []
34 PUBLIC_IPS = []
33
35
34 LOCALHOST = '127.0.0.1'
36 LOCALHOST = ''
35
37
36 def _only_once(f):
38 def _only_once(f):
37 """decorator to only run a function once"""
39 """decorator to only run a function once"""
@@ -51,17 +53,45 b' def _requires_ips(f):'
51 return f(*args, **kwargs)
53 return f(*args, **kwargs)
52 return ips_loaded
54 return ips_loaded
53
55
54 @_only_once
56 def _load_ips_netifaces():
55 def _load_ips():
57 """load ip addresses with netifaces"""
56 """load the IPs that point to this machine
58 import netifaces
59 global LOCALHOST
60 local_ips = []
61 public_ips = []
57
62
58 This function will only ever be called once.
63 # list of iface names, 'lo0', 'eth0', etc.
64 for iface in netifaces.interfaces():
65 # list of ipv4 addrinfo dicts
66 ipv4s = netifaces.ifaddresses(iface).get(netifaces.AF_INET, [])
67 for entry in ipv4s:
68 addr = entry.get('addr')
69 if not addr:
70 continue
71 if not (iface.startswith('lo') or addr.startswith('127.')):
72 public_ips.append(addr)
73 elif not LOCALHOST:
74 LOCALHOST = addr
75 local_ips.append(addr)
76 if not LOCALHOST:
77 # we never found a loopback interface (can this ever happen?), assume common default
78 LOCALHOST = '127.0.0.1'
79 local_ips.insert(0, LOCALHOST)
80 local_ips.extend(['0.0.0.0', ''])
81 LOCAL_IPS[:] = uniq_stable(local_ips)
82 PUBLIC_IPS[:] = uniq_stable(public_ips)
83
84 def _load_ips_gethostbyname():
85 """load ip addresses with socket.gethostbyname_ex
86
87 This can be slow.
59 """
88 """
60 global LOCALHOST
89 global LOCALHOST
61 try:
90 try:
62 LOCAL_IPS[:] = socket.gethostbyname_ex('localhost')[2]
91 LOCAL_IPS[:] = socket.gethostbyname_ex('localhost')[2]
63 except socket.error:
92 except socket.error:
64 pass
93 # assume common default
94 LOCAL_IPS[:] = ['127.0.0.1']
65
95
66 try:
96 try:
67 hostname = socket.gethostname()
97 hostname = socket.gethostname()
@@ -82,6 +112,32 b' def _load_ips():'
82
112
83 LOCALHOST = LOCAL_IPS[0]
113 LOCALHOST = LOCAL_IPS[0]
84
114
115 def _load_ips_dumb():
116 """Fallback in case of unexpected failure"""
117 global LOCALHOST
118 LOCALHOST = '127.0.0.1'
119 LOCAL_IPS[:] = [LOCALHOST, '0.0.0.0', '']
120 PUBLIC_IPS[:] = []
121
122 @_only_once
123 def _load_ips():
124 """load the IPs that point to this machine
125
126 This function will only ever be called once.
127
128 It will use netifaces to do it quickly if available,
129 otherwise it will fallback on socket.gethostbyname_ex, which can be slow.
130 """
131 try:
132 try:
133 _load_ips_netifaces()
134 except ImportError:
135 _load_ips_gethostbyname()
136 except Exception:
137 # unexpected error shouldn't crash, load dumb default values instead.
138 _load_ips_dumb()
139
140
85 @_requires_ips
141 @_requires_ips
86 def local_ips():
142 def local_ips():
87 """return the IP addresses that point to this machine"""
143 """return the IP addresses that point to this machine"""
General Comments 0
You need to be logged in to leave comments. Login now