Python popen не будет работать с блочными устройствами - PullRequest
1 голос
/ 06 декабря 2009

Я выкручиваю небольшое судебно-медицинское приложение, которое пока так выглядит

import time, os,sys

def getter():
    filename = sys.argv[1]
    print "File Entered: " + filename
    os.system('file ' + filename)
    print "\n"
    pipe =  os.popen("xxd " + filename, "r")
    print pipe.read()

Я ввожу через командную строку файл, и он печатает тип файла, а затем предполагается создать канал из терминала обратно в приложение python под именем канала "pipe". Затем я читаю трубу с именем "труба"

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

любые советы, спасибо.

Ответы [ 3 ]

4 голосов
/ 06 декабря 2009

Я предполагаю, что вы пробовали ту же команду из командной строки, и она работала хорошо, даже когда была передана по каналу less или что-то в этом роде.

У меня сильное чувство, что использование subprocess исправит это поведение; Этот модуль заменяет вызов popen, который устарел, и обеспечивает большую степень гибкости при запуске и получении результатов от выполненных команд.

output = Popen(["xxd", "file"], stdout=PIPE).communicate()[0]

Попробуйте запустить процесс под собственной оболочкой и прочитать его канал. Если это по-прежнему не работает, убедитесь, что установлено разумное ограничение на размер буфера, и убедитесь, что вы не используете communicate, что заставит вас ждать завершения процесса (долгое время при работе с блочным устройством).

Прокомментируйте мой ответ, если он не сработал, и постарайтесь точно описать, что не так - это зависание, просто нет вывода или искажены результаты?

3 голосов
/ 06 декабря 2009

Что произойдет, если вы просто запустите xxd /dev/diskwhatever из командной строки? Работает ли и сколько информации выдает? Предполагая, что как суперпользователь у вас есть разрешение на чтение, попытка прочитать все одним махом в последней строке вашего кода будет точкой, где можно ожидать сбоя (поскольку объем информации может быть действительно огромным); Обходной путь должен был бы читать немного за один раз, вместо того, чтобы сделать единственный звонок .read().

Редактировать : получаете ли вы свою трубу в хорошем современном стиле (с subprocess) или устаревшим, но все еще работающим старым способом (с popen), без разницы в этом проблема. В любом случае вы можете получить по одной строке за раз, просто зацикливаясь на объекте pipe, например:

child = subprocess.Popen(whatever, stdout=subprocess.PIPE)
for line in child.stdout:
  print "One more line:", line
1 голос
/ 06 декабря 2009

Проблема, вероятно, связана с тем, как вы вызываете xxd, учитывая, что ваше приложение вообще ничего не делает с файлом.

...