Уведомления

Группа в Telegram: @pythonsu

#1 Июль 11, 2012 15:47:20

_alexs_
Зарегистрирован: 2012-04-02
Сообщения: 42
Репутация: +  0  -
Профиль   Отправить e-mail  

Проверить, есть ли программа в PATH

Для обработки данных вызываю консольное приложение. Но перед вызовом хотелось бы убедиться, что это приложение присутствует в PATH. Пришел к такому решению

def appInstalled():
  myPath = utils.getPath()
  res = 1
  fnull = open( os.devnull, "w" )
  try:
    res = subprocess.call( myPath, stdout = fnull, stderr = fnull )
  except:
    pass
  finally:
    fnull.close()
  if res == 0:
    return True
  else:
    return False
В Linux такая функция работает отлично, а вот в Windows всегда возвращается False. При этом если в except добавить вывод исключений, то видно, что возникает вот такая ошибка
res = subprocess.call( myPath, stdout = fnull, stderr = fnull )
File “C:\Python27\lib\subprocess.py”, line 493, in call
return Popen(*popenargs, **kwargs).wait()
File “C:\Python27\lib\subprocess.py”, line 672, in __init__
errread, errwrite) = self._get_handles(stdin, stdout, stderr)
File “C:\Python27\lib\subprocess.py”, line 784, in _get_handles
p2cread = self._make_inheritable(p2cread)
File “C:\Python27\lib\subprocess.py”, line 823, in _make_inheritable
_subprocess.DUPLICATE_SAME_ACCESS)
WindowsError:
Что делаю не так, в чем ошибка? Может, есть другие кроссплатформенные способы проверить наличие исполнимого файла в PATH?

Офлайн

#2 Июль 11, 2012 16:18:49

fata1ex
От:
Зарегистрирован: 2009-07-11
Сообщения: 732
Репутация: +  52  -
Профиль   Отправить e-mail  

Проверить, есть ли программа в PATH

https://www.google.ru/?q=DUPLICATE_SAME_ACCESS



Отредактировано fata1ex (Июль 11, 2012 23:22:48)

Офлайн

#3 Июль 11, 2012 16:29:41

odnochlen
Зарегистрирован: 2012-06-28
Сообщения: 794
Репутация: +  14  -
Профиль   Отправить e-mail  

Проверить, есть ли программа в PATH

Как говорит гугл, попробуй shell=True

Вместо

  if res == 0:
    return True
  else:
    return False

можно написать
return res==0

Офлайн

#4 Июль 11, 2012 17:04:48

EBFE
Зарегистрирован: 2012-07-03
Сообщения: 99
Репутация: +  20  -
Профиль   Отправить e-mail  

Проверить, есть ли программа в PATH

_alexs_
Для обработки данных вызываю консольное приложение. Но перед вызовом хотелось бы убедиться, что это приложение присутствует в PATH
А не проще сразу ловить исключения при вызове?
что нибудь вроде
def call_app(path):
    try:
        subprocess.call(path)
    except Exception, ex:
        logging.error("Exception: {0}, Path: {1}".format(ex, path))
        print_to_user "Application '{app}' does not exists!".format(app = path)   

Ну или действительно проверить:
http://stackoverflow.com/questions/377017/test-if-executable-exists-in-python

Отредактировано EBFE (Июль 11, 2012 17:05:59)

Офлайн

#5 Июль 11, 2012 17:13:12

_alexs_
Зарегистрирован: 2012-04-02
Сообщения: 42
Репутация: +  0  -
Профиль   Отправить e-mail  

Проверить, есть ли программа в PATH

odnochlen
Как говорит гугл, попробуй shell=True
Результат тот же. Кроме того, использование shell=True потенциально небезопасно.

Попробовал вместо devnull перенаправлять стандартные потоки в subprocess.PIPE, тоже без особого успеха: после вызова call() все подвисает, запущенная программа висит в памяти.

Офлайн

#6 Июль 11, 2012 17:20:49

_alexs_
Зарегистрирован: 2012-04-02
Сообщения: 42
Репутация: +  0  -
Профиль   Отправить e-mail  

Проверить, есть ли программа в PATH

EBFE
А не проще сразу ловить исключения при вызове?
Было бы проще, если бы не одно но. Предложенный вами код
def call_app(path):
    try:
        subprocess.call(path)
    except Exception, ex:
        logging.error("Exception: {0}, Path: {1}".format(ex, path))
        print_to_user "Application '{app}' does not exists!".format(app = path)   
вызовет консольное окно с обширной встроенной справкой злополучного приложения. И пока пользователь это окно не закроет, кина не будет. Вот чтобы этого окна не было (и ничего не надо было закрывать) и нужны перенаправления потоков ввода-вывода.

Да, тот топик на SE уже читал. Мне кажется, предложенный там вариант с самописным which не самый удобный

Отредактировано _alexs_ (Июль 11, 2012 17:24:30)

Офлайн

#7 Июль 11, 2012 20:10:58

reclosedev
От: Н.Новгород
Зарегистрирован: 2012-03-29
Сообщения: 870
Репутация: +  173  -
Профиль   Отправить e-mail  

Проверить, есть ли программа в PATH

Не понял, если нужно просто проверить установлено ли приложение, чем не устраивает проверка на присутствие файла или более продвинутый вариант самодельного which из SO?

Если нужно запустить, перенаправить вывод, и не дожидаясь закрыть процесс, можно попробовать так:

import subprocess
 
def can_execute(*args):
    try:
        process = subprocess.Popen(args, stdout=subprocess.PIPE, 
                                         stderr=subprocess.PIPE)
        process.terminate()
        return True
    except OSError:
        return False
 
print can_execute('ping', '127.0.0.1', '-n', '10')
print can_execute('ping_pong', '127.0.0.1', '-n', '10')

True
False
[Finished in 0.1s]

Отредактировано reclosedev (Июль 11, 2012 20:14:42)

Офлайн

#8 Июль 11, 2012 20:57:45

_alexs_
Зарегистрирован: 2012-04-02
Сообщения: 42
Репутация: +  0  -
Профиль   Отправить e-mail  

Проверить, есть ли программа в PATH

reclosedev
Не понял, если нужно просто проверить установлено ли приложение, чем не устраивает проверка на присутствие файла
Тем, что для проверки на присутствие файла надо знать полный путь к этому файлу. А так, если программа может с равной вероятностью лежать в /usr/bin, /usr/local/bin/, /opt/sometool/, /opt/sometool/bin, ~/bin или еще где-нибудь, аналогично и на Win (Program Files, C:\tool или что-то еще)
reclosedev
или более продвинутый вариант самодельного which из SO?
Да вобщем-то устраивает. Просто, как мне кажется, вариант с попыткой вызова приложения немного проще и эффективнее

reclosedev
Если нужно запустить, перенаправить вывод, и не дожидаясь закрыть процесс, можно попробовать так:
Увы не работает. Точнее, из консоли Python работает, как и мой вариант из первого поста. А вот когда вызывают в GUI получаю DUPLICATE_SAME_ACCESS

Наверное, все же перепишу с использованием самодельного which

Офлайн

#9 Июль 11, 2012 23:19:58

EBFE
Зарегистрирован: 2012-07-03
Сообщения: 99
Репутация: +  20  -
Профиль   Отправить e-mail  

Проверить, есть ли программа в PATH

_alexs_
А вот когда вызывают в GUI
добавте stdin = fnull
Просто по умолчанию subprocess.call(stdin=None) => stdin вызывающего процесса (“child’s file handles will be inherited from the parent”). А в pythonw stdin,stdout,stderr не привязанны:
from sys import stdin, stdout, stderr
with open('stds.txt','a') as f:
f.write("in %d, out %d, err: %d\n" % (stdin.fileno(),
stdout.fileno(), stderr.fileno()))
-----
python: in 0, out 1, err: 2
pythonw: in -2, out -2, err: -2[code]

Отредактировано EBFE (Июль 11, 2012 23:21:09)

Офлайн

#10 Июль 12, 2012 02:25:37

py.user.next
От:
Зарегистрирован: 2010-04-29
Сообщения: 10014
Репутация: +  857  -
Профиль   Отправить e-mail  

Проверить, есть ли программа в PATH

>>> import os.path
>>> 
>>> def f(progname):
...     path = os.getenv('PATH')
...     for p in path.split(':'):
...         if os.path.exists(os.path.join(p, progname)):
...             return True
...     return False
... 
>>> f('grep')
True
>>> f('grepa')
False
>>> f('python2.7')
True
>>> f('python2.6')
True
>>> f('python2.5')
False
>>>



Офлайн

Board footer

Модераторировать

Powered by DjangoBB

Lo-Fi Version