Подпроцесс Python Popen: почему ls *.txt не работает?

Я просматривал этот вопрос.

В моем случае я хочу сделать:

import subprocess
p = subprocess.Popen(['ls', 'folder/*.txt'], stdout=subprocess.PIPE, 
                                 stderr=subprocess.PIPE)

out, err = p.communicate()

Теперь я могу проверить в командной строке, что работает "ls folder/*.txt", так как в папке много файлов .txt.

Но в Python (2.6) я получаю:

ls: невозможно получить доступ * : Нет такого файла или каталога

Я пробовал делать: r'folder/\*.txt' r"folder/\*.txt" r'folder/\\*.txt' и другие варианты, но, похоже, Popen совсем не нравится символ *.

Есть ли другой способ сбежать от *?


person aaa    schedule 14.12.2012    source источник
comment
Сбежать? Я думаю, что вы хотите сначала развернуть *, а затем запустить команду ls. Почитайте о расширении оболочки.   -  person Trygve Laugstøl    schedule 14.12.2012


Ответы (2)


*.txt автоматически расширяется вашей оболочкой в ​​file1.txt file2.txt .... Если вы процитируете *.txt, это не сработает:

[~] ls "*.py"                                                                  
ls: cannot access *.py: No such file or directory
[~] ls *.py                                                                    
file1.py  file2.py file3.py

Если вы хотите получить файлы, соответствующие вашему шаблону, используйте glob:

>>> import glob
>>> glob.glob('/etc/r*.conf')
['/etc/request-key.conf', '/etc/resolv.conf', '/etc/rc.conf']
person Blender    schedule 14.12.2012
comment
Спасибо. При использовании Popen в Python вы должны использовать кавычки. См. связанный ответ или документацию Python. - person aaa; 14.12.2012
comment
@aaa: проблема заключалась в том, что вы не использовали оболочку, которая не допускала подстановки. Вызов ls с Popen - не лучшая идея, IMO, поскольку Python предоставляет для этого лучшие инструменты. - person Blender; 14.12.2012
comment
аааа, теперь понял. Да, вы правы, библиотека glob намного лучше. Видите ли, я только что узнал новую вещь :) - person aaa; 14.12.2012

Вы можете передать параметр shell в True. Это позволит глобировать.

import subprocess
p = subprocess.Popen('ls folder/*.txt',
                     shell=True,
                     stdout=subprocess.PIPE, 
                     stderr=subprocess.PIPE)
out, err = p.communicate()
person Thomas Ruiz    schedule 14.12.2012
comment
Да, это работает. Я неправильно предположил, что аргументы для Popen должны быть выстроены в массив, так как это делают все примеры. - person aaa; 14.12.2012
comment
p.communicate() является блокирующим вызовом, можем ли мы иметь такое же поведение в неблокирующей манере? Благодарность - person Anurag; 14.12.2012