2011-02-11 3 views
64

Что делать в командной строке:Python: как перенаправить вывод с подпроцессом?

cat file1 file2 file3 > myfile 

То, что я хочу сделать с питоном:

import subprocess, shlex 
my_cmd = 'cat file1 file2 file3 > myfile' 
args = shlex.split(my_cmd) 
subprocess.call(args) # spits the output in the window i call my python program 
+0

Выполнение такой команды в подпроцессе не даст вам никакого выхода. Может быть, вы хотите запустить его без _> myfile_ перенаправления вывода из _cat file1 file2 file3_ в python? – PoltoS

+0

@PoltoS Я хочу присоединиться к некоторым файлам, а затем обработать полученный файл. Я думал, что использование кошки было самой простой альтернативой. Есть ли лучший/pythonic способ сделать это? – catatemypythoncode

+0

Возможно решение 'os.sendfile()', см. [Воспроизводить команду unix cat в python] (http://stackoverflow.com/q/11532980/4279) – jfs

ответ

23

UPDATE: os.system не рекомендуется, хотя и по-прежнему доступны в Python 3.


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

os.system(my_cmd) 

Если вы действительно хотите использовать подпроцесс, вот решение (в основном сняты из документации подпроцесса):

p = subprocess.Popen(my_cmd, shell=True) 
os.waitpid(p.pid, 0) 

Ото, вы можете избежать системных вызовов полностью:

import shutil 

with open('myfile', 'w') as outfile: 
    for infile in ('file1', 'file2', 'file3'): 
     shutil.copyfileobj(open(infile), outfile) 
+1

Это работает, но позвольте мне спросить вас: в чем смысл библиотеки подпроцессов, если os.system уже выполнила свою работу? Мне кажется, что я должен был использовать подпроцесс, потому что это библиотека, посвященная этой задаче, хотя, поскольку я делаю это только для себя, я буду в порядке использовать os.system на этот раз. – catatemypythoncode

+0

Библиотека подпроцессов гораздо более гибкая, чем 'os.system', и может точно моделировать' os.system', но с ней также сложнее работать. –

+11

'os.system' пришел до' подпроцесса'. Первый - это устаревший API, который последний намеревается заменить. – Santa

4

@ PoltoS Я хочу присоединиться к некоторым файлам, а затем обработать полученный файл. Я думал, что использование кошки было самой простой альтернативой. Есть ли лучший/pythonic способ сделать это?

Конечно:

with open('myfile', 'w') as outfile: 
    for infilename in ['file1', 'file2', 'file3']: 
     with open(infilename) as infile: 
      outfile.write(infile.read()) 
165

Чтобы ответить на исходный вопрос, для перенаправления вывода, просто передать открытый дескриптор файла для stdout аргумент subprocess.call в:

# Use a list of args instead of a string 
input_files = ['file1', 'file2', 'file3'] 
my_cmd = ['cat'] + input_files 
with open('myfile', "w") as outfile: 
    subprocess.call(my_cmd, stdout=outfile) 

Но как и другие что использование внешней команды, такой как cat, для этой цели совершенно постороннее.

+2

Это должен быть ответ на общий вопрос о трубопроводе при использовании оболочки из Python. –

+25

Это правильный ответ, а не тот, который указан как правильный. –

+0

Это правильный ответ, лучший подход. –

0

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

import subprocess32 as sub 

with open("A.csv","a") as f: 
    f.flush() 
    sub.Popen(["cat","temp.csv"],stdout=f) 
0
size = 'ffprobe -v error -show_entries format=size -of default=noprint_wrappers=1:nokey=1 dump.mp4 > file' 
proc = subprocess.Popen(shlex.split(size), shell=True) 
time.sleep(1) 
proc.terminate() #proc.kill() modify it by a suggestion 
size = "" 
with open('file', 'r') as infile: 
    for line in infile.readlines(): 
     size += line.strip() 

print(size) 
os.remove('file') 

При использовании подпроцесс, процесс должен быть killed.This является example.If вы не убить процесс, файл будет пустым, и вы можете прочитать nothing.It может работать на Windows. Я не могу убедиться, что он может работать на Unix.

+0

Это плохой пример кода (он не будет работать в Unix, он демонстрирует плохие практики 'для строки в .readlines():', 's + =') и 'proc.kill()' может привести к потере информации в общем случае (он не позволяет закончить законченный процесс (в Unix) - нераскрытый контент теряется). Во всяком случае, примечание о буферизации более подходит в качестве комментария. – jfs

+0

Я запустил его на Windows в порядке (потому что kill равно завершению в Windows). В Unix можно использовать proc.terminate(). @ J.F. Sebastian. Я не имею системы Unix на своем компьютере. – wyx

+0

Если вы находитесь в Windows, отбросьте 'shlex.split()', поместите 'shell = True', drop'> file', drop 'open()' и т. Д. И используйте 'stdout = PIPE',' Timer (1, proc.terminate) .start() '; 'output = proc.communicate() [0]' вместо этого. Вот [полный пример] (http://stackoverflow.com/a/27995163/4279). Дополнительные решения: [Остановить вывод процесса вывода в Python без зависания?] (Http://stackoverflow.com/q/4417962/4279) Примечание: в вопросе нет требования о необходимости завершения дочернего процесса вручную - вы может обратиться к другим вопросам, например, процесс может вести себя по-разному, если его stdout является tty, но он не соответствует теме. – jfs