Проверка связи с серверами на Python

Есть ли в Python способ проверить связь с сервером через ICMP и вернуть значение ИСТИНА, если сервер отвечает, или ЛОЖЬ, если ответа нет?


person Kudu    schedule 01.06.2010    source источник
comment
связанные: Пинговать сайт в Python?   -  person jfs    schedule 02.11.2012


Ответы (27)


Эта функция работает в любой ОС (Unix, Linux, macOS и Windows)
Python 2 и Python 3

РЕДАКТИРОВАТЬ:
Автор @radato os.system был заменен на subprocess.call. Это позволяет избежать уязвимости инъекции оболочки в случаях, когда строка вашего имени хоста не может быть проверена.

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

Обратите внимание, что, согласно @ikrase в Windows, эта функция по-прежнему будет возвращать True, если вы получите ошибку Destination Host Unreachable.

Объяснение

Команда - это ping как в Windows, так и в Unix-подобных системах.
Параметр -n (Windows) или -c (Unix) контролирует количество пакетов, которое в этом примере было установлено равным 1.

platform.system() возвращает имя платформы. Бывший. 'Darwin' в macOS.
subprocess.call() выполняет системный вызов. Бывший. subprocess.call(['ls','-l']).

person ePi272314    schedule 20.09.2015
comment
Обратите внимание, что это все равно вернет истину (в Windows), если вы получите ответ о недоступности целевого хоста от другого хоста. - person ikrase; 29.12.2016
comment
Я обнаружил, что иногда получаю успешный пинг, когда мой модем выключен ??? Это тестирование 8.8.8.8 и google.com в ОС Windows 10. Что-то не так. - person Markus; 10.11.2018
comment
Этого не может случиться @Markus. Пожалуйста, протестируйте вручную и с модифицированной версией приведенного выше кода и сообщите нам результат. Вручную: 1) открыть cmd 2) ping 8.8.8.8 -n 1 3) echo %ERRORLEVEL%. Код: измените последнюю строку кода Python на return system_call(command). При правильном подключении вы получите 0 (ноль). При выключенном модеме вы должны получить код ошибки. Конечно, оба метода должны возвращать один и тот же код ошибки при одинаковых условиях. - person ePi272314; 12.11.2018
comment
Это произошло, и я использовал точный код, слово в слово. Я понимаю и верю вашим комментариям, пинг командной строки не может быть успешным, когда нет соединения, поэтому я подумал, что что-то не работает правильно в python для работы с командной строкой. Я попробую обновить и посмотрю, как оно пойдет. Спасибо. - person Markus; 13.11.2018
comment
@Markus см. Комментарий Икрасе. - person Boris; 26.01.2019
comment
Я единственный здесь, кто заметил, что system.call - опечатка и должна быть subprocess.call? - person ishahak; 07.03.2019
comment
Ты прав. Кто-то отредактировал мой первоначальный ответ. Я исправлю это. Спасибо - person ePi272314; 08.03.2019
comment
Как нам получить время отклика как переменную? - person Stevoisiak; 24.06.2019
comment
Как бы вы сделали кросс-совместимый флаг тайм-аута? - person joe_04_04; 15.05.2021

Если вам не нужна поддержка Windows, вот действительно краткий способ сделать это:

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!'

Это работает, потому что ping возвращает ненулевое значение в случае сбоя соединения. (На самом деле возвращаемое значение различается в зависимости от сетевой ошибки.) Вы также можете изменить время ожидания проверки связи (в секундах) с помощью параметра «-t». Обратите внимание, это выведет текст на консоль.

person Scott    schedule 01.05.2012
comment
Я остановился на этом варианте response = os.system("ping -c 1 -w2 " + hostname + " > /dev/null 2>&1") - person MGP; 14.08.2013
comment
@ jeckyll2hide man ping, отправьте только 1 пакет с крайним сроком 2 секунды и перенаправьте весь вывод в / dev / null, получите только возвращаемое значение. - person MGP; 06.05.2014
comment
@ManuelGutierrez Я думаю, вы хотите -W 2000 (тайм-аут после 2000 миллисекунд) и, возможно, -t 3 (выход через 3 секунды, несмотря ни на что) - person eludom; 19.10.2014
comment
Вы пропустили цитату hostname! - person hek2mgl; 11.05.2015
comment
-w и -W принимают значения в секундах, а не в миллисекундах. Чтобы убедиться, проверьте man ping. - person Alan Turing; 15.06.2015
comment
Мне просто любопытно - почему это на самом деле не работает в Windows? - person Source Matters; 13.11.2018
comment
@SourceMatters Параметр для указания количества пакетов отличается для Windows (-n) и unix (-c). - person yeaske; 15.11.2018
comment
Ааааааааааааааааааааааааааааааааааааа круто В конечном итоге я вместо этого выполнил второй ответ и проанализировал вывод, поскольку я также стал жертвой ответов о недоступности хоста назначения. - person Source Matters; 16.11.2018
comment
Если вы получите строку hostname от пользователя, он может легко взломать ваш сервер, предоставив вам URL-адрес типа 'google.com; rm -rf /*'. Вместо этого используйте subprocess.run(["ping", "-c", "1", hostname]).returncode. - person Boris; 26.01.2019
comment
Как нам узнать время отклика на пинг? - person Stevoisiak; 24.06.2019
comment
Вот мое решение из Python 3.6 с использованием более новой версии subprocess.run: command = ["ping", "-c", "1", "-w2", host] return subprocess.run(args=command, stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL).returncode == 0 - person Ian Colwell; 29.06.2021

Для этого существует модуль под названием pyping. Его можно установить с помощью пипса

pip install pyping

Он довольно прост в использовании, однако при использовании этого модуля вам понадобится root-доступ, поскольку он создает необработанные пакеты под капотом.

import pyping

r = pyping.ping('google.com')

if r.ret_code == 0:
    print("Success")
else:
    print("Failed with {}".format(r.ret_code))
person Stephen Cochran    schedule 08.10.2015
comment
Обратите внимание, что сообщения ICMP могут быть отправлены только процессами, запущенными с правами root (в Windows вы должны запускать этот сценарий как «Администратор»). - person Ben Hyde; 20.01.2017
comment
Мне нравится, что вы можете указать тайм-аут и количество отправленных ICMP-запросов. Мне удалось написать сценарий, который обнаруживает все хосты в локальной подсети. Он выполняется за 1 секунду вместо 255 секунд при использовании решения os.system('ping -c 1 -t 1 hostname'). Кроме того, pyping lib очень проста в использовании по сравнению с использованием библиотеки сокетов TCP / IP. Я написал свою программу ping, используя оба, и pyping, на мой взгляд, намного быстрее и проще в использовании, особенно если кто-то не знаком с использованием библиотеки сокетов TCP / IP. - person MikeyE; 24.11.2017
comment
не работает с py3. ModuleNotFoundError: нет модуля с именем core - person alireza; 26.03.2018
comment
"основная" ошибка возникает из-за несовместимости с python3. Я пытался исправить это для python3, но он постоянно присылает мне ошибки. страница авторов и проектов на github не работает (404 не найдено). нам придется самостоятельно портировать его на python3 :-) - person Andre; 02.11.2018
comment
для python3 попробуйте ping3: github.com/kyan001/ping3 pip install ping3 - person beep_check; 03.01.2019
comment
@alireza - я тоже с этим сталкивался. Возможно, это поможет: stackoverflow.com/questions / 35330964 / - person Guy Avraham; 14.03.2019
comment
ping3: res = ping ('8.8.8.8') Отслеживание (последний вызов последний): Файл ‹stdin›, строка 1, в ‹module› файле /home/env-admin/.local/lib/python3.6/site -packages / ping3.py, строка 165, в ping с socket.socket (socket.AF_INET, socket.SOCK_RAW, socket.IPPROTO_ICMP) как sock: Файл /usr/lib/python3.6/socket.py, строка 144, в init _socket.socket .__ init __ (self, family, type, proto, fileno) PermissionError: [Errno 1] Операция запрещена - person xCovelus; 25.10.2019

Для python3 существует очень простой и удобный модуль python ping3: (pip install ping3, требуется root привилегии).

from ping3 import ping, verbose_ping
ping('example.com')  # Returns delay in seconds.
>>> 0.215697261510079666

Этот модуль также позволяет настраивать некоторые параметры.

person Александр Рублев    schedule 21.12.2017
comment
Как отредактировано, требуются права root, обсуждение отмены этого здесь: github.com/kyan001/ping3/issues/ 10 - person Dimitrios Mistriotis; 17.03.2020
comment
Уж нужен root prvilege не только для установки, но и для исполнения: ping (example.com) - person Clock ZHONG; 31.03.2020

Поскольку мне нравится иметь универсальную программу Python для версий 2.7 и 3.x, а также для платформ Linux, Mac OS и Windows, мне пришлось изменить существующие примеры.

# shebang does not work over all platforms
# ping.py  2016-02-25 Rudolf
# subprocess.call() is preferred to os.system()
# works under Python 2.7 and 3.4
# works under Linux, Mac OS, Windows

def ping(host):
    """
    Returns True if host responds to a ping request
    """
    import subprocess, platform

    # Ping parameters as function of OS
    ping_str = "-n 1" if  platform.system().lower()=="windows" else "-c 1"
    args = "ping " + " " + ping_str + " " + host
    need_sh = False if  platform.system().lower()=="windows" else True

    # Ping
    return subprocess.call(args, shell=need_sh) == 0

# test call
print(ping("192.168.17.142"))
person Rudolf    schedule 25.02.2016
comment
Вместо False if platform.system().lower()=="windows" else True вы, конечно, можете просто использовать platform.system().lower() != "windows". - person Frerich Raabe; 13.05.2016
comment
os.name!="nt" тоже не работает? По общему признанию, я не пробовал это со всеми комбинациями версий / платформ! - person Keeely; 11.01.2017
comment
В моем случае шлюз по умолчанию возвращает сообщение «недоступен», но команда Windows ping по-прежнему имеет код возврата 0. Итак, этот подход сработал (извините за форматирование - его 6 строк, включая объявление функции): 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 - person wellspokenman; 19.03.2018
comment
@wellspokenman, вы бы предпочли вернуть 0, если unreachable найден в трубе, не так ли? - person beeb; 25.05.2018
comment
@beeb да, я тоже это сделал, но забыл обновить комментарий. Моя текущая функция выглядит так: pastebin.com/FEYWsVjK - person wellspokenman; 14.06.2018
comment
Спасибо @wellspokenman, здесь у меня почти ничего не работало правильно под Windows, пока я не попробовал ваше решение, опубликованное на pastebin.com. Спасибо. К тому же это очень быстро. - person MKANET; 06.04.2020

Программный пинг ICMP сложен из-за повышенных привилегий, необходимых для отправки необработанных пакетов ICMP, а вызов двоичного файла ping уродлив. Для мониторинга сервера вы можете добиться того же результата, используя метод под названием TCP ping:

# pip3 install tcping
>>> from tcping import Ping
# Ping(host, port, timeout)
>>> ping = Ping('212.69.63.54', 22, 60)
>>> ping.ping(3)
Connected to 212.69.63.54[:22]: seq=1 time=23.71 ms
Connected to 212.69.63.54[:22]: seq=2 time=24.38 ms
Connected to 212.69.63.54[:22]: seq=3 time=24.00 ms

Внутренне это просто устанавливает TCP-соединение с целевым сервером и немедленно разрывает его, измеряя прошедшее время. Эта конкретная реализация немного ограничена тем, что она не обрабатывает закрытые порты, но для ваших собственных серверов она работает довольно хорошо.

person kravietz    schedule 15.02.2018
comment
Такая стратегия также полезна, когда на сервере есть брандмауэр, который отбрасывает настоящие пинги ICMP! Кроме того, вот страница GitHub: github.com/zhengxiaowai/tcping - person Jerther; 25.11.2020

Осмотревшись, я закончил писать свой собственный модуль ping, который предназначен для мониторинга большого количества адресов, является асинхронным и не использует много системных ресурсов. Вы можете найти его здесь: https://github.com/romana/multi-ping/ Он лицензирован Apache, поэтому вы можете использовать его в своем проекте любым удобным для вас способом.

Основными причинами для реализации моего собственного являются ограничения других подходов:

  • Многие из упомянутых здесь решений требуют выполнения команды exec в утилите командной строки. Это довольно неэффективно и требует больших ресурсов, если вам нужно отслеживать большое количество IP-адресов.
  • Другие упоминают некоторые старые модули ping python. Я посмотрел на них и, в конце концов, все они имели ту или иную проблему (например, некорректную установку идентификаторов пакетов) и не обрабатывали пинг большого количества адресов.
person Juergen Brendel    schedule 17.08.2017
comment
Хороший товарищ по работе! Если кто-то хочет увидеть это в действии, просто используйте github.com/romana /multi-ping/blob/master/demo.py - person Cucu; 05.06.2018
comment
Стоит отметить, что для этого также требуются права root. - person Jann Poppinga; 17.12.2020

Убедитесь, что pyping установлен, или установите его pip install pyping

#!/usr/bin/python
import pyping

response = pyping.ping('Your IP')

if response.ret_code == 0:
    print("reachable")
else:
    print("unreachable")
person Naveen    schedule 16.12.2015
comment
Спасибо! Однако мне нужно запустить этот код от имени пользователя root, чтобы он заработал. - person Thomas; 15.08.2016
comment
Страница Pyping на GitHub больше не существует, а Пакет PyPI не обновлялся с 2016 года. - person Stevoisiak; 25.06.2019
comment
У меня следующие ошибки: import pyping Traceback (последний вызов последний): Файл ‹stdin›, строка 1, в ‹module› Файл /usr/local/lib/python3.6/dist-packages/pyping/__init__.py, строка 3, в ‹module› из импорта ядра * ModuleNotFoundError: нет модуля с именем 'core' - person Clock ZHONG; 31.03.2020

Моя версия функции ping:

  • Работает на Python 3.5 и новее, в Windows и Linux (должно работать на Mac, но не могу его протестировать).
  • В Windows возвращает False, если команда ping завершилась неудачно с "Destination Host Unreachable".
  • И не показывает никаких выходных данных ни в виде всплывающего окна, ни в командной строке.
import platform, subprocess

def ping(host_or_ip, packets=1, timeout=1000):
    ''' Calls system "ping" command, returns True if ping succeeds.
    Required parameter: host_or_ip (str, address of host to ping)
    Optional parameters: packets (int, number of retries), timeout (int, ms to wait for response)
    Does not show any output, either as popup window or in command line.
    Python 3.5+, Windows and Linux compatible (Mac not tested, should work)
    '''
    # The ping command is the same for Windows and Linux, except for the "number of packets" flag.
    if platform.system().lower() == 'windows':
        command = ['ping', '-n', str(packets), '-w', str(timeout), host_or_ip]
        # run parameters: capture output, discard error messages, do not show window
        result = subprocess.run(command, stdin=subprocess.DEVNULL, stdout=subprocess.PIPE, stderr=subprocess.DEVNULL, creationflags=0x08000000)
        # 0x0800000 is a windows-only Popen flag to specify that a new process will not create a window.
        # On Python 3.7+, you can use a subprocess constant:
        #   result = subprocess.run(command, capture_output=True, creationflags=subprocess.CREATE_NO_WINDOW)
        # On windows 7+, ping returns 0 (ok) when host is not reachable; to be sure host is responding,
        # we search the text "TTL=" on the command output. If it's there, the ping really had a response.
        return result.returncode == 0 and b'TTL=' in result.stdout
    else:
        command = ['ping', '-c', str(packets), '-w', str(timeout), host_or_ip]
        # run parameters: discard output and error messages
        result = subprocess.run(command, stdin=subprocess.DEVNULL, stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL)
        return result.returncode == 0

Не стесняйтесь использовать его по своему усмотрению.

person Jose Francisco Lopez Pimentel    schedule 12.04.2019

Я решаю это с помощью:

def ping(self, host):
    res = False

    ping_param = "-n 1" if system_name().lower() == "windows" else "-c 1"

    resultado = os.popen("ping " + ping_param + " " + host).read()

    if "TTL=" in resultado:
        res = True
    return res

TTL - это способ узнать, правильно ли выполнен пинг. Салудос

person user3620655    schedule 06.09.2017

Мое сокращение с использованием идей из ответов в этом сообщении, но только с использованием нового рекомендованного модуля подпроцесса и python3:

import subprocess
import platform

operating_sys = platform.system()
nas = '192.168.0.10'

def ping(ip):
    # ping_command = ['ping', ip, '-n', '1'] instead of ping_command = ['ping', ip, '-n 1'] for Windows
    ping_command = ['ping', ip, '-n', '1'] if operating_sys == 'Windows' else ['ping', ip, '-c 1']
    shell_needed = True if operating_sys == 'Windows' else False

    ping_output = subprocess.run(ping_command,shell=shell_needed,stdout=subprocess.PIPE)
    success = ping_output.returncode
    return True if success == 0 else False

out = ping(nas)
print(out)
person Arno    schedule 20.08.2016
comment
Вам не нужно использовать True if condition else False для возврата True или False в зависимости от условия. Просто используйте, например, shell_needed = operating_sys == 'Windows' и return success == 0 - person emorris; 13.02.2017

Этот сценарий работает в Windows и должен работать в других операционных системах: он работает в Windows, Debian и macosx, требуется тестирование в Solaris.

import os
import platform


def isUp(hostname):

    giveFeedback = False

    if platform.system() == "Windows":
        response = os.system("ping "+hostname+" -n 1")
    else:
        response = os.system("ping -c 1 " + hostname)

    isUpBool = False
    if response == 0:
        if giveFeedback:
            print hostname, 'is up!'
        isUpBool = True
    else:
        if giveFeedback:
            print hostname, 'is down!'

    return isUpBool

print(isUp("example.com")) #Example domain
print(isUp("localhost")) #Your computer
print(isUp("invalid.example.com")) #Unresolvable hostname: https://tools.ietf.org/html/rfc6761
print(isUp("192.168.1.1")) #Pings local router
print(isUp("192.168.1.135")) #Pings a local computer - will differ for your network
person Matthew    schedule 13.02.2015
comment
Хороший ответ. Здесь не требуются права администратора для Windows. - person mountainclimber11; 09.01.2018
comment
В любом случае получаю True как правильный, так и неправильный IP - person joash; 25.02.2020
comment
Да, это определенно не работает. Просто возвращает: true в любом случае в Windows - person MKANET; 06.04.2020

В итоге я нашел этот вопрос относительно аналогичного сценария. Я пробовал использовать pyping, но пример, приведенный Naveen, не работал у меня в Windows под Python 2.7.

Пример, который сработал для меня:

import pyping

response = pyping.send('Your IP')

if response['ret_code'] == 0:
    print("reachable")
else:
    print("unreachable")
person Templar    schedule 28.12.2015
comment
pyping не является стандартным модулем. Не могли бы вы дать ссылку? - person Mawg says reinstate Monica; 22.03.2016

Используя Multi-ping (pip install multiPing), я сделал этот простой код (просто скопируйте и вставьте, если хотите!):

from multiping import MultiPing

def ping(host,n = 0):
    if(n>0):
        avg = 0
        for i in range (n):
            avg += ping(host)
        avg = avg/n
    # Create a MultiPing object to test hosts / addresses
    mp = MultiPing([host])

    # Send the pings to those addresses
    mp.send()

    # With a 1 second timout, wait for responses (may return sooner if all
    # results are received).
    responses, no_responses = mp.receive(1)


    for addr, rtt in responses.items():
        RTT = rtt


    if no_responses:
        # Sending pings once more, but just to those addresses that have not
        # responded, yet.
        mp.send()
        responses, no_responses = mp.receive(1)
        RTT = -1

    return RTT

Использование:

#Getting the latency average (in seconds) of host '192.168.0.123' using 10 samples
ping('192.168.0.123',10)

Если вам нужен единственный образец, второй параметр «10» можно игнорировать!

Надеюсь, это поможет!

person Geraldo Neto    schedule 02.12.2017
comment
отличная библиотека, но нужны привилегии root. - person Craynic Cai; 03.02.2018

Мне нужна была более быстрая проверка связи, и я не хотел использовать какие-либо внешние библиотеки, поэтому решил использовать параллелизм с использованием встроенного asyncio.

Для этого кода требуется python 3.7+, он создан и протестирован только на Linux. Он не будет работать в Windows, но я уверен, что вы можете легко изменить его для работы в Windows.

Я не эксперт в asyncio, но я использовал эту замечательную статью Ускорьте свою программу Python с помощью параллелизма и я придумал эти строки кода. Я постарался сделать его максимально простым, поэтому, скорее всего, вам нужно будет добавить в него больше кода в соответствии с вашими потребностями.

Он не возвращает true или false, я подумал, что было бы удобнее просто заставить его печатать IP, который отвечает на запрос ping. Я думаю, что это довольно быстро, пингует 255 ips почти за 10 секунд.

#!/usr/bin/python3

import asyncio

async def ping(host):
    """
    Prints the hosts that respond to ping request
    """
    ping_process = await asyncio.create_subprocess_shell("ping -c 1 " + host + " > /dev/null 2>&1")
    await ping_process.wait()

    if ping_process.returncode == 0:
        print(host)
    return 


async def ping_all():
    tasks = []

    for i in range(1,255):
        ip = "192.168.1.{}".format(i)
        task = asyncio.ensure_future(ping(ip))
        tasks.append(task)

    await asyncio.gather(*tasks, return_exceptions = True)

asyncio.run(ping_all())

Пример вывода:

192.168.1.1
192.168.1.3
192.168.1.102
192.168.1.106
192.168.1.6

Обратите внимание, что IP-адреса не в порядке, поскольку IP-адрес печатается, как только он отвечает, поэтому тот, который отвечает первым, печатается первым.

person Ahmed Essam    schedule 13.03.2020

Кажется достаточно простым, но меня не устраивало. Я продолжал получать сообщение «icmp open socket operation not allowed», иначе решения зависли бы, если бы сервер был отключен. Однако если вы хотите знать, что сервер активен и на нем запущен веб-сервер, то curl выполнит свою работу. Если у вас есть ssh и сертификаты, тогда будет достаточно ssh и простой команды. Вот код:

from easyprocess import EasyProcess # as root: pip install EasyProcess
def ping(ip):
    ping="ssh %s date;exit"%(ip) # test ssh alive or
    ping="curl -IL %s"%(ip)      # test if http alive
    response=len(EasyProcess(ping).call(timeout=2).stdout)
    return response #integer 0 if no response in 2 seconds
person user2099484    schedule 10.02.2015

У меня было аналогичное требование, поэтому я реализовал его, как показано ниже. Он протестирован на 64-битной Windows и Linux.

import subprocess
def systemCommand(Command):
    Output = ""
    Error = ""     
    try:
        Output = subprocess.check_output(Command,stderr = subprocess.STDOUT,shell='True')
    except subprocess.CalledProcessError as e:
        #Invalid command raises this exception
        Error =  e.output 

    if Output:
        Stdout = Output.split("\n")
    else:
        Stdout = []
    if Error:
        Stderr = Error.split("\n")
    else:
        Stderr = []

    return (Stdout,Stderr)

#in main
Host = "ip to ping"
NoOfPackets = 2
Timeout = 5000 #in milliseconds
#Command for windows
Command = 'ping -n {0} -w {1} {2}'.format(NoOfPackets,Timeout,Host)
#Command for linux 
#Command = 'ping -c {0} -w {1} {2}'.format(NoOfPackets,Timeout,Host)
Stdout,Stderr = systemCommand(Command)
if Stdout:
   print("Host [{}] is reachable.".format(Host))
else:
   print("Host [{}] is unreachable.".format(Host))

Когда IP недоступен, subprocess.check_output () вызывает исключение. Дополнительная проверка может быть выполнена путем извлечения информации из выходной строки «Пакеты: отправлено = 2, принято = 2, потеряно = 0 (потеря 0%)».

person Luminos    schedule 21.05.2015

Вот решение с использованием модуля Python subprocess и инструмента ping CLI, предоставляемого базовой ОС. Проверено на Windows и Linux. Поддержка настройки тайм-аута сети. Не требует прав root (по крайней мере, в Windows и Linux).

import platform
import subprocess

def ping(host, network_timeout=3):
    """Send a ping packet to the specified host, using the system "ping" command."""
    args = [
        'ping'
    ]

    platform_os = platform.system().lower()

    if platform_os == 'windows':
        args.extend(['-n', '1'])
        args.extend(['-w', str(network_timeout * 1000)])
    elif platform_os in ('linux', 'darwin'):
        args.extend(['-c', '1'])
        args.extend(['-W', str(network_timeout)])
    else:
        raise NotImplemented('Unsupported OS: {}'.format(platform_os))

    args.append(host)

    try:
        if platform_os == 'windows':
            output = subprocess.run(args, check=True, universal_newlines=True).stdout

            if output and 'TTL' not in output:
                return False
        else:
            subprocess.run(args, check=True)

        return True
    except (subprocess.CalledProcessError, subprocess.TimeoutExpired):
        return False
person Epoc    schedule 13.02.2018

Используйте это, он протестирован на python 2.7 и отлично работает, он возвращает время пинга в миллисекундах в случае успеха и возвращает False в случае неудачи.

import platform,subproccess,re
def Ping(hostname,timeout):
    if platform.system() == "Windows":
        command="ping "+hostname+" -n 1 -w "+str(timeout*1000)
    else:
        command="ping -i "+str(timeout)+" -c 1 " + hostname
    proccess = subprocess.Popen(command, stdout=subprocess.PIPE)
    matches=re.match('.*time=([0-9]+)ms.*', proccess.stdout.read(),re.DOTALL)
    if matches:
        return matches.group(1)
    else: 
        return False
person MSS    schedule 11.04.2015

ТОЛЬКО ДЛЯ WINDOWS - не могу поверить, что никто не взломал Win32_PingStatus. Используя простой запрос WMI, мы бесплатно возвращаем объект, полный действительно подробной информации.

import wmi


# new WMI object
c = wmi.WMI()

# here is where the ping actually is triggered
x = c.Win32_PingStatus(Address='google.com')

# how big is this thing? - 1 element
print 'length x: ' ,len(x)


#lets look at the object 'WMI Object:\n'
print x


#print out the whole returned object
# only x[0] element has values in it
print '\nPrint Whole Object - can directly reference the field names:\n'
for i in x:
    print i



#just a single field in the object - Method 1
print 'Method 1 ( i is actually x[0] ) :'
for i in x:
    print 'Response:\t', i.ResponseTime, 'ms'
    print 'TTL:\t', i.TimeToLive


#or better yet directly access the field you want
print '\npinged ', x[0].ProtocolAddress, ' and got reply in ', x[0].ResponseTime, 'ms'

образец вывода

person Aimondy    schedule 08.06.2018

Я заимствую из других ответов. Попытка упростить и свести к минимуму запросы.

import platform, os

def ping(host):
    result = os.popen(' '.join(("ping", ping.param, host))).read()
    return 'TTL=' in result

ping.param = "-n 1" if platform.system().lower() == "windows" else "-c 1"
person misantroop    schedule 26.10.2018

используя пакет сокетов в python3:

import socket

def ping_server(server: str, port: int, timeout=3):
    """ping server"""
    try:
        socket.setdefaulttimeout(timeout)
        s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
        s.connect((server, port))
    except OSError as error:
        return False
    else:
        s.close()
        return True
person abrhije    schedule 22.04.2021

Пингуйте их все в Windows или Linux, верните отсортированный список. Это гибрид / исправление из ответов @Ahmed Essam и @Arno.

import asyncio
import re

import platform
isWindows = platform.system()


async def ping(host):
    cmd = 'ping {} {} 1'.format(host, '-n' if isWindows else '-c')
    ping_proc = \
        await asyncio.create_subprocess_shell(cmd, stdout=asyncio.subprocess.PIPE,
                                                      stderr=asyncio.subprocess.PIPE)
    stdout, stderr = await ping_proc.communicate()
    outstr = stdout.decode()

    if ping_proc.returncode == 0:
        delay = int(re.search(r'(?:time=)([\d]*)', outstr).group(1)) if 'time=' in outstr else -1
        if delay >= 0:
            # print('{} {}ms'.format(host, delay))
            return [host, delay]

    return [host, None]


async def ping_all():
    tasks = []

    for i in range(1, 256):
        ip = "192.168.1.{}".format(i)
        task = asyncio.ensure_future(ping(ip))
        tasks.append(task)

    retList = await asyncio.gather(*tasks, return_exceptions=True)
    retList = [x for x in retList if x[1] is not None]
    retList.sort(key=lambda x: int(x[0].split('.')[-1]))

    return retList


loop = asyncio.ProactorEventLoop()
asyncio.set_event_loop(loop)
pingRet = loop.run_until_complete(ping_all())

for ip, d in pingRet:
    print('{:<16s} {}ms'.format(ip, d))
person nimig18    schedule 28.05.2021

Одна вещь, которую упускают из виду многие ответы, заключается в том, что (по крайней мере, в Windows) команда ping возвращает 0 (что означает успех), если она получает ответ «Целевой хост недоступен».

Вот мой код, который проверяет, есть ли b'TTL=' в ответе, поскольку он присутствует только тогда, когда ping достиг хоста. Примечание. Большая часть этого кода основана на других ответах здесь.

import platform
import subprocess

def ping(ipAddr, timeout=100):
    '''
    Send a ping packet to the specified host, using the system ping command.
    Accepts ipAddr as string for the ping destination.
    Accepts timeout in ms for the ping timeout.
    Returns True if ping succeeds otherwise Returns False.
        Ping succeeds if it returns 0 and the output includes b'TTL='
    '''
    if platform.system().lower() == 'windows':
        numFlag = '-n'
    else:
        numFlag = '-c'
    completedPing = subprocess.run(['ping', numFlag, '1', '-w', str(timeout), ipAddr],
                                   stdout=subprocess.PIPE,    # Capture standard out
                                   stderr=subprocess.STDOUT)  # Capture standard error
    # print(completedPing.stdout)
    return (completedPing.returncode == 0) and (b'TTL=' in completedPing.stdout)

print(ping('google.com'))

Примечание. Это захватывает вывод, а не печатает его, поэтому, если вы хотите увидеть вывод ping, вам нужно будет распечатать completedPing.stdout перед возвратом.

person Brent Robertson    schedule 02.03.2018

  1 #!/usr/bin/python
  2
  3 import os
  4 import sys
  5 import time
  6
  7 os.system("clear")
  8 home_network = "172.16.23."
  9 mine = []
 10
 11 for i in range(1, 256):
 12         z =  home_network + str(i)
 13         result = os.system("ping -c 1 "+ str(z))
 14         os.system("clear")
 15         if result == 0:
 16                 mine.append(z)
 17
 18 for j in mine:
 19         print "host ", j ," is up"

Простой, который я приготовил за минуту ... использование icmplib требует root-прав, как показано ниже, работает довольно хорошо! HTH

person user3423128    schedule 15.03.2014

person    schedule
comment
Единственная проблема в том, что это не работает в Windows. - person Kudu; 02.06.2010
comment
Следует упомянуть, что причина того, что это необходимо, заключается в том, что ICMP требует root, а / bin / ping обходит это, задав SUID. - person Catskul; 25.02.2013
comment
Примечание. Может завершиться ошибкой, если ping находится в другом месте. Используйте whereis ping, чтобы получить правильный путь. - person octern; 21.05.2013
comment
Это работает в Windows: ping_response = subprocess.Popen(["ping", hostname, "-n", '1'], stdout=subprocess.PIPE).stdout.read() - person Victor Lellis; 05.03.2015
comment
Как я могу проанализировать результат, чтобы проверить, был ли ответ в Windows нормально или нет? - person Pitto; 15.09.2015
comment
Чтобы создать аргументы подпроцесса, я обычно делаю "ping -c1 -w100 192.168.0.1".split() - person xtofl; 26.09.2015
comment
Если вы хотите только 0 или 1, в качестве ответа: ping_response = subprocess.call(["ping", "-c1", "-w100", "10.0.0.254"], stdout=subprocess.DEVNULL) - person Dysmas; 09.01.2020
comment
Вышеупомянутое решение не работает в Windows даже после адаптации: subprocess.call(["ping", "-n", "1", "10.0.0.24"]) Всегда возвращает 0. - person Dysmas; 09.01.2020

person    schedule
comment
В этом коде может быть ответ на вопрос, но было бы полезно добавить некоторые комментарии или объяснения того, как ваш код решает проблему. - person skrrgwasme; 01.10.2014