Почему мой код подпроцесса Python не работает?

from subprocess import *

test = subprocess.Popen('ls')
print test

Когда я пытаюсь запустить этот простой код, я получаю сообщение об ошибке:

WindowsError: [Error 2] The system cannot find the file specified

Я понятия не имею, почему я не могу заставить этот простой код работать, и это расстраивает, любая помощь будет очень признательна!


person BesaseB    schedule 14.05.2013    source источник
comment
у вас есть ls.exe в вашем пути? подождите, какую ОС вы используете?   -  person zenpoy    schedule 14.05.2013
comment
Да, так как мне сообщить системе Windows о команде ls?   -  person BesaseB    schedule 14.05.2013
comment
@user2371187 user2371187 Если вам нужен список файлов, проще использовать os.listdir()< /а>.   -  person Aya    schedule 14.05.2013
comment
в windows нет ls (кроме powershell/mingw32); он использует dir   -  person Amelia    schedule 14.05.2013


Ответы (2)


Похоже, вы хотите сохранить результат вызова subprocess.Popen().
Для получения дополнительной информации см. Подпроцесс — Popen.communicate(input=None).

>>> import subprocess
>>> test = subprocess.Popen('ls', stdout=subprocess.PIPE)
>>> out, err = test.communicate()
>>> print out
fizzbuzz.py
foo.py
[..]

Однако в оболочке Windows (cmd.exe) нет команды ls, но есть две другие альтернативы:

Используйте os.listdir(). Этот метод следует предпочесть, так как с ним намного проще работать:

>>> import os
>>> os.listdir("C:\Python27")
['DLLs', 'Doc', 'include', 'Lib', 'libs', 'LICENSE.txt', 'NEWS.txt', 'python.exe
', 'pythonw.exe', 'README.txt', 'tcl', 'Tools', 'w9xpopen.exe']

Использовать Powershell — устанавливается по умолчанию в более новых версиях Windows (>= Windows 7):

>>> import subprocess
>>> test = subprocess.Popen(['powershell', '/C', 'ls'], stdout=subprocess.PIPE)
>>> out, err = test.communicate()
>>> print out


    Directory: C:\Python27


Mode                LastWriteTime     Length Name
----                -------------     ------ ----
d----        14.05.2013     16:00            DLLs
d----        14.05.2013     16:01            Doc
[..]

Команды оболочки с использованием cmd.exe будут выглядеть примерно так:

test = subprocess.Popen(['cmd', '/C', 'ipconfig'], stdout=subprocess.PIPE)

Для получения дополнительной информации см.:
полезный и аккуратный модуль подпроцесса - Запуск команд в эмуляторе терминала - Windows


Примечания:

person timss    schedule 14.05.2013
comment
Я все еще получаю ту же ошибку Windows .. :( - person BesaseB; 14.05.2013
comment
@user2371187 user2371187 Я запускаю Python в Linux, но не могли бы вы попробовать мое последнее редактирование? Popen('cmd', '/C', 'ls')? - person timss; 14.05.2013
comment
@timss По умолчанию в Windows нет ни двоичного файла ls, ни команды с таким именем в cmd.exe. В powershell.exe есть один, хотя его вывод значительно отличается от ls в Unix. os.listdir(), вероятно, самый простой способ воспроизвести ls в Windows. - person Aya; 14.05.2013
comment
@Aya А, да, конечно. Прошло некоторое время с тех пор, как я использовал cmd.exe. Я обновлю свой ответ. - person timss; 14.05.2013
comment
@timss FWIW, subprocess.Popen(['powershell', '/C', 'ls']) будет работать, но анализировать вывод было бы затруднительно. - person Aya; 14.05.2013
comment
Да, я пробовал, когда я распечатал его, я получил объект ‹subprocess.Popen по адресу 0x0256FC10› - person BesaseB; 14.05.2013
comment
@Aya Спасибо, снова обновил мой ответ. Я бы тоже осмелился разобрать его, когда я пытаюсь, это выглядит как полный беспорядок. - person timss; 14.05.2013
comment
@ user2371187 Я обновил свой ответ, вы должны использовать stdout=subprocess.PIPE. Но опять же, вы должны просто использовать os.listdir(). - person timss; 14.05.2013
comment
@timss Я все еще получаю какой-то шестнадцатеричный базовый адрес, я не знаю, правильно это или нет, но это то, что я получаю, лол - person BesaseB; 14.05.2013
comment
@user2371187 user2371187 Тогда вы делаете что-то не так. Я только что проверил, и он работает просто отлично. Обратите внимание, что это точно так же, как и первый блок кода, просто заменяющий вызов subprocess.Popen(): /а> - person timss; 14.05.2013
comment
@timss Да, теперь он просто работает вечно и не останавливается ... Я понятия не имею, лол, у меня точно такой же код, как у тебя - person BesaseB; 14.05.2013
comment
@user2371187 user2371187 Я пробовал использовать как интерпретатор/оболочку Python, так и python.exe ls.py в cmd.exe, и оба они отлично работают в Windows 7 x64. Какая у вас версия? У вас вообще есть Powershell? Тест с вводом powershell в cmd.exe - person timss; 14.05.2013
comment
@timiss: То же самое происходит и со мной: PowerShell загружается около 50 часов. Кажется, это проблема на некоторых ПК. А у меня версия 3.0. - person kirbyfan64sos; 14.05.2013
comment
@ kirbyfan64sos Не удивлюсь, но для меня это действительно быстро, даже с суперфрагментированным жестким диском и всем остальным. Но опять же, нет причин использовать Powershell для ls. Если ls - это просто пример, возможно, вместо этого может работать cmd.exe (если OP хочет выполнить команду оболочки). - person timss; 14.05.2013
comment
@ user2371187 Я вижу, что вы задали новый вопрос. Не стесняйтесь пометить ответ как принятый, если вы считаете, что этот ответ решен этот вопрос (хотя я вижу, что вы также использовали shell=True). - person timss; 14.05.2013
comment
@timss: я не знаю, в чем проблема со скоростью, но я уже видел два других ПК с этой проблемой. Повезло тебе! Это единственная причина, по которой мне не нравится Powershell. - person kirbyfan64sos; 15.05.2013

Согласен с timss; В Windows нет команды ls. Если вам нужен список каталогов, подобный ls в Windows, используйте dir /B для одного столбца или dir /w /B для нескольких столбцов. Или просто используйте os.listdir. Если вы используете dir, вы должны запустить подпроцесс, используя subprocess.Popen(['dir', '/b'], shell=True). Если вы хотите сохранить вывод, используйте subprocess.Popen(['dir', '/b'], shell=True, stdout=subprocess.PIPE). И причина, по которой я использовал shell=True, заключается в том, что, поскольку dir является внутренней командой DOS, для ее вызова необходимо использовать оболочку. Параметр /b удаляет заголовок, а параметр /w принудительно выводит в несколько столбцов.

person kirbyfan64sos    schedule 14.05.2013