Pinging servers in Python
Solution 1
This function works in any OS (Unix, Linux, macOS, and Windows)
Python 2 and Python 3
EDITS:
By @radato os.system
was replaced by subprocess.call
. This avoids shell injection vulnerability in cases where your hostname string might not be validated.
import platform # For getting the operating system name
import subprocess # For executing a shell command
def ping(host):
"""
Returns True if host (str) responds to a ping request.
Remember that a host may not respond to a ping (ICMP) request even if the host name is valid.
"""
# Option for the number of packets as a function of
param = '-n' if platform.system().lower()=='windows' else '-c'
# Building the command. Ex: "ping -c 1 google.com"
command = ['ping', param, '1', host]
return subprocess.call(command) == 0
Note that, according to @ikrase on Windows this function will still return True
if you get a Destination Host Unreachable
error.
Explanation
The command is ping
in both Windows and Unix-like systems.
The option -n
(Windows) or -c
(Unix) controls the number of packets which in this example was set to 1.
platform.system()
returns the platform name. Ex. 'Darwin'
on macOS.
subprocess.call()
performs a system call. Ex. subprocess.call(['ls','-l'])
.
Solution 2
If you don't need to support Windows, here's a really concise way to do it:
import os
hostname = "google.com" #example
response = os.system("ping -c 1 " + hostname)
#and then check the response...
if response == 0:
print hostname, 'is up!'
else:
print hostname, 'is down!'
This works because ping returns a non-zero value if the connection fails. (The return value actually differs depending on the network error.) You could also change the ping timeout (in seconds) using the '-t' option. Note, this will output text to the console.
Solution 3
There is a module called pyping that can do this. It can be installed with pip
pip install pyping
It is pretty simple to use, however, when using this module, you need root access due to the fact that it is crafting raw packets under the hood.
import pyping
r = pyping.ping('google.com')
if r.ret_code == 0:
print("Success")
else:
print("Failed with {}".format(r.ret_code))
Solution 4
import subprocess
ping_response = subprocess.Popen(["/bin/ping", "-c1", "-w100", "192.168.0.1"], stdout=subprocess.PIPE).stdout.read()
Solution 5
For python3 there's a very simple and convenient python module ping3: (pip install ping3
, needs root privileges).
from ping3 import ping, verbose_ping
ping('example.com') # Returns delay in seconds.
>>> 0.215697261510079666
This module allows for the customization of some parameters as well.
Related videos on Youtube
Kudu
Updated on May 05, 2022Comments
-
Kudu about 2 years
In Python, is there a way to ping a server through ICMP and return TRUE if the server responds, or FALSE if there is no response?
-
jfs over 11 yearsrelated: Ping a site in Python?
-
-
Kudu almost 14 yearsThe only problem with this is that it wouldn't work on Windows.
-
Catskul about 11 yearsIt should be mentioned that the reason something like this is necessary is that ICMP requires root, and /bin/ping gets around this by being set SUID.
-
octern almost 11 yearsNote: May fail if ping is in a different location. Use
whereis ping
to get the correct path. -
MGP over 10 yearsI ended up with this variant
response = os.system("ping -c 1 -w2 " + hostname + " > /dev/null 2>&1")
-
MGP about 10 years@jeckyll2hide man ping, send just 1 packet with deadline 2 seconds and redirect all output to /dev/null, retrieve just the return value.
-
skrrgwasme over 9 yearsThis code may have the answer to the question, but it would be helpful to add some comments or explanation of how your code is solving the problem.
-
eludom over 9 years@ManuelGutierrez I think you want "-W 2000" (timeout after 2000 milliseconds) and maybe "-t 3" (exit after 3 seconds, no matter what)
-
Victor Lellis about 9 yearsThis works on Windows:
ping_response = subprocess.Popen(["ping", hostname, "-n", '1'], stdout=subprocess.PIPE).stdout.read()
-
hek2mgl almost 9 yearsYou missed to quote
hostname
! -
Alan Turing almost 9 years-w and -W take values in seconds not milliseconds. Check
man ping
to make sure. -
Pitto over 8 yearsHow can I parse the result to check if the response was ok or ko in Windows?
-
xtofl over 8 yearsTo create the subprocess arguments, I usually do
"ping -c1 -w100 192.168.0.1".split()
-
Mawg says reinstate Monica about 8 years
pyping
does not appear to be a standard module. Perhaps you could provide a link? -
Frerich Raabe almost 8 yearsInstead of
False if platform.system().lower()=="windows" else True
you could of course also just useplatform.system().lower() != "windows"
. -
Thomas over 7 yearsThanks! However, I need to run this code as root to make it work.
-
ikrase over 7 yearsNote that this will still return true (on Windows) if you get a "destination host unreachable" reply from a different host.
-
Keeely over 7 yearsDoesn't
os.name!="nt"
also work? Admittedly I've not tried it on all ver/platform combos! -
Ben Hyde over 7 years"Note that ICMP messages can only be sent from processes running as root (in Windows, you must run this script as ‘Administrator’)."
-
emorris about 7 yearsYou don't need to use
True if condition else False
for returning True or False based on a condition. Just use e.g.shell_needed = operating_sys == 'Windows'
andreturn success == 0
-
MikeyE over 6 yearsI like that you can specify the timeout and count of ICMP requests sent. I was able to write a script which discovers all hosts on the local sub-net. It executes in 1 second, instead of 255 seconds using the
os.system('ping -c 1 -t 1 hostname')
solution. Plus thepyping
lib is very easy to use compared to using the TCP/IP sockets library. I wrote my ping program using both, andpyping
is far quicker and easier to use, in my opinion, especially if one isn't familiar with using the TCP/IP sockets library. -
mountainclimber11 over 6 yearsGood answer. No admin rights required for Windows here.
-
Craynic Cai over 6 yearsawesome library, but need root privileges.
-
womblerone about 6 yearsIn my case the default gateway returns an 'unreachable' message, but the windows ping command still has a return code of 0. So this approach worked (sorry for the formatting - its 6 lines, including the functiontion declaration):
def ping(host): process = subprocess.Popen(["ping", "-n", "1",host], stdout=subprocess.PIPE, stderr=subprocess.PIPE) streamdata = process.communicate()[0] if 'unreachable' in str(streamdata): return 1 return process.returncode
-
alireza about 6 yearsnot work with py3. ModuleNotFoundError: No module named 'core'
-
beeb almost 6 years@wellspokenman you would rather return 0 if
unreachable
is found in the pipe, no? -
Cucu almost 6 yearsNice job mate! If anyone wants to see it in action, just use github.com/romana/multi-ping/blob/master/demo.py
-
womblerone almost 6 years@beeb yeah I did that too but forgot to update the comment. My current function looks like this: pastebin.com/FEYWsVjK
-
Andre over 5 yearsthe 'core' error comes from an incompatibility with python3. i tried to fix it for python3 but it constantly keeps sending me errors. the authors and projects github page is down (404 not found). we'll have to port it by ourselves to python3 :-)
-
Markus over 5 yearsI'm finding that I will occasionally get a ping success when my modem is off??? That's testing "8.8.8.8" and "google.com" on a Windows 10 OS. Something is not quite right.
-
ePi272314 over 5 yearsThat cannot happen @Markus. Please, test by hand and with a modified version of the code above, and tell us the result. By hand: 1) open cmd 2)
ping 8.8.8.8 -n 1
3)echo %ERRORLEVEL%
. Code: Modify the last line of the Python code toreturn system_call(command)
. With proper connectivity you will get 0 (zero). With your modem off, you must get some error code. Of course, both methods must return the same error code under same conditions. -
Markus over 5 yearsIt did happen and I was using the exact code, word for word. I understand and belief your comments, there is no way a command line ping could succeed when there in no connection, hence my thought something wasn't working correctly in the python to command line operation. I'll give the update a try and see how it goes. Thanks.
-
Source Matters over 5 yearsI'm just curious - why won't this actually work on Windows?
-
yeaske over 5 years@SourceMatters The param to specify number of packets is different for windows (-n) and unix (-c).
-
Source Matters over 5 yearsAhh ok cool! I ultimately ended up doing the 2nd Answer instead, and parse the output, as I was a victim of the "Destination Host Unreachable" responses as well.
-
beep_check over 5 yearsfor python3 try ping3: github.com/kyan001/ping3
pip install ping3
-
Boris Verkhovskiy over 5 yearsIf you get the
hostname
string from a user, they could easily hack your server by giving you a "url" like'google.com; rm -rf /*'
. Usesubprocess.run(["ping", "-c", "1", hostname]).returncode
instead. -
Boris Verkhovskiy over 5 years@Markus see ikrase's comment.
-
ishahak about 5 yearsAm I the only one here to notice that
system.call
is a typo and should besubprocess.call
? -
ePi272314 about 5 yearsYou are right. Some one edited my original answer. I will fix that. Thanks
-
Guy Avraham about 5 years@alireza - I have encountered it as well. Maybe this will help: stackoverflow.com/questions/35330964/…
-
Stevoisiak almost 5 yearsHow would we get the ping response time?
-
Stevoisiak almost 5 yearsHow would we get the response time as a variable?
-
Stevoisiak almost 5 yearsPyping's GitHub page no longer exists and the PyPI package has not been updated since 2016.
-
xCovelus over 4 yearsping3: res = ping('8.8.8.8') Traceback (most recent call last): File "<stdin>", line 1, in <module> File "/home/env-admin/.local/lib/python3.6/site-packages/ping3.py", line 165, in ping with socket.socket(socket.AF_INET, socket.SOCK_RAW, socket.IPPROTO_ICMP) as sock: File "/usr/lib/python3.6/socket.py", line 144, in init _socket.socket.__init__(self, family, type, proto, fileno) PermissionError: [Errno 1] Operation not permitted
-
Dysmas over 4 yearsIf you want only 0 or 1, as a response :
ping_response = subprocess.call(["ping", "-c1", "-w100", "10.0.0.254"], stdout=subprocess.DEVNULL)
-
Dysmas over 4 yearsThe above solution does not work in Windows, even when adapted :
subprocess.call(["ping", "-n", "1", "10.0.0.24"])
It always returns 0. -
joash about 4 yearsAm either way receiving True both a right and wrong IP
-
Dimitrios Mistriotis about 4 yearsAs edited requires root privileges, discussion on lifting this here: github.com/kyan001/ping3/issues/10
-
Clock ZHONG about 4 yearsOh, need root prvilege not only for install, but also for execution: ping("example.com")
-
Clock ZHONG about 4 yearsI got thefollowing errors: import pyping Traceback (most recent call last): File "<stdin>", line 1, in <module> File "/usr/local/lib/python3.6/dist-packages/pyping/__init__.py", line 3, in <module> from core import * ModuleNotFoundError: No module named 'core'
-
MKANET about 4 yearsYeah this definitely doesn't work. Just returns :"true" either way on Windows
-
MKANET about 4 yearsThanks @wellspokenman, pretty much nothing here worked for me correctly under Windows until I tried your solution posted on pastebin.com. Thank you. It's also very fast.
-
Jerther over 3 yearsSuch strategy is also useful when the server has a firewall that drops real ICMP pings! Also, here's the GitHub page: github.com/zhengxiaowai/tcping
-
Jann Poppinga over 3 yearsIt's worth mentioning that this too requires root privileges.
-
joe_04_04 almost 3 yearsHow would you make a cross-compatible timeout flag?
-
Ian Colwell almost 3 yearsHere's my solution from Python 3.6, using the newer
subprocess.run
:command = ["ping", "-c", "1", "-w2", host]
return subprocess.run(args=command, stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL).returncode == 0
-
Joshua almost 3 yearsI can confirm that the windows ping command is hokey with its return value. I am pinging a system I have disconnected from the network, another IP is responding that it isn't available, but I am getting 0% loss and an ERRORLEVEL of 0. Here is a paste of the results pastebin.pl/view/2437bb7c
-
Amandeep Chugh over 2 yearsThis doesn't need sudo for execution. I'm running python 3.8.10
-
NeilG over 2 yearsNot ICMP but great way to test connection when you can't rely on underlying OS calls. And compact.
-
Billy Cao over 2 yearsOn Windows, ping -w argument takes MILISECONDS.
-
ratijas over 2 yearsTimeout is measured in seconds, not milliseconds, so a default value of 1000 is unlikely to be useful. Please edit to just "1".
-
Jose Francisco Lopez Pimentel over 2 years@ratijas Timeout parameter must be passed in milliseconds, in Windows and Linux. I have just looked for the Mac OS command, and it uses seconds; but anyway, I can't test it on a Mac.
-
Olivier B. about 2 yearsThis doesn't work on OSX.
-w
does not exist ->-W
; and it returns False when the ping call actually pings. -
Olivier B. about 2 yearsThis seem to works great, but ttl is lowercase on OSX on the ping command output, so for it to works, you need
return 'TTL=' in result or 'ttl=' in result
-
Sany about 2 yearsIf this doesn't work well on windows, it would be good to remove it from the title. This is not the super-universal solution.
-
Sany about 2 yearsNo problem wit
Destination Host Unreachable
error - see comment above from @ikrase ? -
ePi272314 about 2 yearsHello @Sany. This solution woks on Windows. The problem reported by ikrase could be solved. I can image two ways of doing that. However, I do not have any installation of Windows available to try. Maybe somebody in a future could improve the answer by including that fix.
-
Florent almost 2 yearsIn a Celery task and Python 3 it returns
FileNotFoundError: [Errno 2] No such file or directory: 'ping': 'ping'