2009-12-06 2 views
1

я сверну небольшой судебно-приложение, которое выглядит как этот до сих порPython POPEN обыкновение работать с блочными устройствами

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() 

I вход через командную строку массива и он печатает тип файла, а затем она является предположительно, чтобы создать канал от терминала обратно к приложению python под названием трубы «pipe». Затем я прочитал трубу под названием «труба»

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

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

+0

'popen' устарел. Вместо этого используйте модуль 'subprocess'. – badp

+0

Что означает устаревшее? – Recursion

+0

Устаревшее означает, что теперь есть более эффективные способы выполнения одной и той же задачи, и устаревшие способы будут удалены с языка в какой-то момент в будущем. – badp

ответ

3

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

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

child = subprocess.Popen(whatever, stdout=subprocess.PIPE) 
for line in child.stdout: 
    print "One more line:", line 
+1

Вот и все. Попробуйте напечатать pipe.read (1), и вы можете получить некоторые данные. – arhuaco

+0

Большое спасибо Alex, он отлично поработал. – Recursion

+0

+1 Хороший! Идем использовать эту нотацию. –

1

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

+0

... если ваша проблема на самом деле не используется, вы можете использовать объект pipe popen. – badp

+0

, когда я запускаю его в терминале, он отлично работает. Он также отлично подходит для небольшого текстового файла. – Recursion

4

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

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

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

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

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

+0

Что я могу использовать, чтобы вытащить данные по одной строке за раз, а не общаться? это то, что у меня до сих пор "pipe = subprocess.Popen ([" xxd ", filename], stdout = subprocess.PIPE) « – Recursion

+0

@Recursion, я только что отредактировал свой ответ, чтобы показать, что это сводится к выполнению' для строки в pipe.stdout: '. –