Подтвердить что ты не робот

Проверьте, существует ли программа из python script

Как проверить, существует ли программа из python script?

Предположим, вы хотите проверить, доступны ли wget или curl. Мы предположим, что они должны быть в пути.

Было бы лучше увидеть многоплатформенное решение, но на данный момент Linux достаточно.

Советы:

  • выполнение команды и проверка кода возврата не всегда достаточно, так как некоторые инструменты возвращают результат не 0, даже если вы пытаетесь выполнить --version.
  • ничто не должно отображаться на экране при проверке команды

Кроме того, я был бы признателен за решение, которое является более общим, например is_tool(name)

4b9b3361

Ответ 1

import subprocess
import os

def is_tool(name):
    try:
        devnull = open(os.devnull)
        subprocess.Popen([name], stdout=devnull, stderr=devnull).communicate()
    except OSError as e:
        if e.errno == os.errno.ENOENT:
            return False
    return True

Ответ 2

shutil.which

Позвольте мне порекомендовать вариант, который еще не обсуждался: реализация Python which, в частности shutil.which. Он был представлен в Python 3.3 и является кросс-платформенным, поддерживающим Linux, Mac и Windows. Он также доступен в Python 2.x через whichcraft. Вы также можете просто скопировать код which прямо из

distutils.spawn.find_executable

Другой вариант, который уже упоминался, - distutils.spawn.find_executable.

find_executable docstring выглядит следующим образом:

Пытается найти "исполняемый файл" в каталогах, перечисленных в "пути"

Итак, если вы обратите внимание, вы заметите, что имя функции несколько вводит в заблуждение. В отличие от which, find_executable на самом деле не проверяет, что executable помечен как исполняемый файл, только то, что он находится в PATH. Таким образом, вполне возможно (что маловероятно), что find_executable указывает, что программа доступна, когда она отсутствует.

Например, предположим, что у вас есть файл /usr/bin/wget, который не отмечен как исполняемый. Запуск wget из оболочки приведет к следующей ошибке: bash:/usr/bin/wget: Permission denied. which('wget') is not None вернет False, но find_executable('wget') is not None вернет True. Вероятно, вам удастся использовать любую функцию, но об этом просто нужно знать с помощью find_executable.

def is_tool(name):
    """Check whether `name` is on PATH."""

    from distutils.spawn import find_executable

    return find_executable(name) is not None

Ответ 3

Самый простой способ - попытаться запустить программу с нужными параметрами и обработать исключение, если оно не существует:

try:
    subprocess.call(["wget", "your", "parameters", "here"])
except OSError as e:
    if e.errno == errno.ENOENT:
        # handle file not found error.
    else:
        # Something else went wrong while trying to run 'wget'
        raise

Это обычный шаблон в Python: EAFP

Ответ 4

Вы можете использовать вызов подпроцесса в двоичный файл, необходимый с помощью:

  • "which": * nix
  • "where": Win 2003 и более поздние версии (Xp имеет аддон)

чтобы получить исполняемый путь (предположим, что он находится в пути к среде).

import os 
import platform
import subprocess

cmd = "where" if platform.system() == "Windows" else "which"
try: 
    subprocess.call([cmd, your_executable_to_check_here])
except: 
    print "No executable"

или просто используйте Ned Batchelder wh.py script, то есть "какую" кроссплатформенную реализацию:

http://nedbatchelder.com/code/utilities/wh_py.html

Ответ 5

Я бы пошел за:

import distutils.spawn

def is_tool(name):
  return distutils.spawn.find_executable(name) is not None

Ответ 6

Я бы, вероятно, выложил в which wget или which curl и проверил, что результат заканчивается именем программы, которую вы используете. Магия юникса :)

На самом деле все, что вам нужно сделать, это проверить код возврата which. Итак... используя наш надежный модуль subprocess:

import subprocess

rc = subprocess.call(['which', 'wget'])
if rc == 0:
    print 'wget installed!'
else:
    print 'wget missing in path!'

Обратите внимание, что я проверял это на Windows с Cygwin... Если вы хотите выяснить, как реализовать which в чистом Python, я предлагаю вам проверить здесь: http://pypi.python.org/pypi/pycoreutils (о дорогой - кажется, они не снабжение which. Время для дружеского толчка?)

ОБНОВЛЕНИЕ: В Windows вы можете использовать where вместо which для аналогичного эффекта.

Ответ 7

Я бы изменил ответ @sorin следующим образом, причина в том, что он будет проверять имя программы без прохождения абсолютного пути к программе

from subprocess import Popen, PIPE

def check_program_exists(name):
    p = Popen(['/usr/bin/which', name], stdout=PIPE, stderr=PIPE)
    p.communicate()
    return p.returncode == 0

Ответ 8

import os
import subprocess


def is_tool(prog):
    for dir in os.environ['PATH'].split(os.pathsep):
        if os.path.exists(os.path.join(dir, prog)):
            try:
                subprocess.call([os.path.join(dir, prog)],
                                stdout=subprocess.PIPE,
                                stderr=subprocess.STDOUT)
            except OSError, e:
                return False
            return True
    return False

Ответ 9

Небольшая модификация кода @SvenMarnach, которая устраняет проблему печати в стандартный выходной поток. Если вы используете функцию subprocess.check_output(), а не subprocess.call(), тогда вы можете обрабатывать строку, которая обычно печатается стандартным образом в вашем коде, и все еще ловить исключения и код состояния выхода.

Если вы хотите подавить стандартный выходной поток в терминале, не печатайте строку std out, которая возвращается из check_output:

import subprocess
import os
try:
    stdout_string = subprocess.check_output(["wget", "--help"], stderr=subprocess.STDOUT)
    # print(stdout_string)
except subprocess.CalledProcessError as cpe:
    print(cpe.returncode)
    print(cpe.output)
except OSError as e:
    if e.errno == os.errno.ENOENT:
        print(e)
    else:
        # Something else went wrong while trying to run `wget`
        print(e)

Не нулевой код статуса выхода и строка вывода повышены в CalledProcessError как subprocess.CalledProcessError.returncode и subprocess.CalledProcessError.output, чтобы вы могли делать с ними все, что захотите.

Если вы хотите распечатать исполняемый стандартный вывод на терминал, напечатайте возвращаемую строку:

import subprocess
import os
try:
    stdout_string = subprocess.check_output(["wget", "--help"], stderr=subprocess.STDOUT)
    print(stdout_string)
except subprocess.CalledProcessError as cpe:
    print(cpe.returncode)
    print(cpe.output)
except OSError as e:
    if e.errno == os.errno.ENOENT:
        print(e)
    else:
        # Something else went wrong while trying to run `wget`
        print(e)

print() добавляет дополнительную строку строки строки. Если вы хотите устранить это (и записать std-ошибку в std-поток err-потока вместо потока std out, как показано выше с помощью операторов print(), используйте sys.stdout.write(string) и sys.stderr.write(string) вместо print():

import subprocess
import os
import sys
try:
    stdout_string = subprocess.check_output(["bogus"], stderr=subprocess.STDOUT)
    sys.stdout.write(stdout_string)
except subprocess.CalledProcessError as cpe:
    sys.stderr.write(cpe.returncode)
    sys.stderr.write(cpe.output)
except OSError as e:
    if e.errno == os.errno.ENOENT:
        sys.stderr.write(e.strerror)
    else:
        # Something else went wrong while trying to run `wget`
        sys.stderr.write(e.strerror)

Ответ 10

Для систем на базе Debian:

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

Вы можете использовать разные команды для получения разных типов установленных пакетов, Примеры: https://askubuntu.com/info/17823/how-to-list-all-installed-packages

Два, которые я нашел лучше всего:

dpkg --get-selections           # big list
aptitude search '~i!~M' -F      # great list

Вы можете запустить их в терминале, чтобы проверить их.


Функция python:

import os,sys

def check_for_program(program):

    if not os.path.exists("/tmp/program_list"):
        os.system("aptitude search '~i!~M' -F > /tmp/program_list")

    with open('/tmp/program_list') as f:
        for line in f:
            if program in line:
                return True
    return False