O Windows não consegue encontrar o arquivo em subprocess.call ()

103

Eu estou recebendo o seguinte erro:

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

Meu código é:

subprocess.call(["<<executable file found in PATH>>"])

Windows 7 de 64 bits. Python 3.x mais recente, estável.

Alguma ideia?

Obrigado,

Sri
fonte
e o que é esse arquivo executável?
SilentGhost
A parte executável "android" do Android SDK
Sri
2
E se é acessível em PATH
Sri
você pode executá-lo a partir da linha de comando?
SilentGhost
Um pequeno histórico do que estou tentando realizar. Isso é para Opendevice - um projeto de código aberto para converter aplicativos HTML5 em aplicativos específicos para dispositivos. Estou tentando substituir os.system () em bitbucket.org/srirangan/opendevice/src/tip/tools/net/srirangan/… para subprocess.call ()
Sri

Respostas:

178

Quando o comando é um shell embutido, adicione 'shell = True' à chamada.

Por exemplo, para dirvocê digitaria:

import subprocess
subprocess.call('dir', shell=True)

Para citar a documentação:

A única vez que você precisa especificar shell = True no Windows é quando o comando que você deseja executar está embutido no shell (por exemplo, dir ou copiar). Você não precisa de shell = True para executar um arquivo em lote ou executável baseado em console.

Douglas Macdonald
fonte
14
Isso ocorre porque nenhum executável é chamado dir.exeenquanto houver um /bin/lsin * nix. diré implementado por CMD.EXE muito como cdé implementado pela festa .
Apalala
1
Isso é fortemente desencorajado. docs.python.org/2/library/…
nu everest
11
@nueverest Somente quando a string de comando é construída a partir de uma entrada externa
Jirka
A alternativa (mais segura para entrada externa) é obter o PATHdo os.environe pesquisá-lo manualmente.
asmeurer de
Consulte stackoverflow.com/a/32799942/3912576 para obter uma solução muito mais apropriada para esse problema.
SimonBiggs
33

No Windows, acredito que o subprocessmódulo não fica no a PATHmenos que você passeshell=True porque ele usa CreateProcess()nos bastidores. No entanto, shell=Truepode ser um risco de segurança se você passar argumentos que podem vir de fora do seu programa. Para tornar, subprocessno entanto, capaz de encontrar o executável correto, você pode usar shutil.which. Suponha que o executável em seu PATHseja denominado frob:

subprocess.call([shutil.which('frob'), arg1, arg2])

(Isso funciona no Python 3.3 e superior.)

ptomato
fonte
4
Qualquer opção de python 2?
Naramsim
1
Você está certo e está sugerindo a maneira certa de consertar. Esta resposta deve ser aceita. A resposta aceita atualmente não explica a causa e sugere uma solução que pode ser perigosa em alguns casos.
David Ferenczy Rogožan
18

No Windows, você deve chamar por meio do cmd.exe. Como Apalala mencionou, os comandos do Windows são implementados em cmd.exe não como executáveis ​​separados.

por exemplo

subprocess.call(['cmd', '/c', 'dir'])

/ c diz ao cmd para executar o comando a seguir

Isso é mais seguro do que usar shell = True, que permite injeções de shell.

Sam Inverso
fonte
Como manteria a tela aberta?
Moondra de
2
@Moondra, Se bem entendi, tente em /kvez de /c. Digite cmd /?na linha de comando para obter detalhes.
User5910
@ User5910 Obrigado. Vou tentar quando tiver uma chance.
Moondra de
3

Se você estiver usando o PowerShell, então estará subprocess.call(['powershell','-command','dir']). O Powershell suporta uma grande parte dos comandos POSIX

Darksnake
fonte
2

Depois de muito questionar, descobri que executar um arquivo localizado em C: \ Windows \ System32 \ enquanto uma versão de 32 bits do python em uma máquina de 64 bits é um problema potencial, porque o Windows está tentando superar o processo, e redirecionar chamadas para C: \ Windows \ System32 para C: \ Windows \ SysWOW64.

Encontrei um exemplo de como corrigir isso aqui: http://code.activestate.com/recipes/578035-disable-file-system-redirector/

RBN
fonte
1

Para citar a documentação:

"Antes do Python 3.5, essas três funções compreendiam a API de alto nível para subprocessar. Agora você pode usar run () em muitos casos, mas muitos códigos existentes chamam essas funções."

SO: em vez de subprocess.call, use subprocess.run para Python 3.5 e superior

Adrian Berca
fonte
Verdadeiro e útil.
Erick G. Hagstrom
0

Eu encontrei o mesmo problema enquanto chamava um PHP. A razão é que o PHP não está no PATH, então o comando PHP não foi encontrado. Mas o PowerShell descobriu que ele existe no local atual e sugere a substituição de 'PHP' por '. \ PHP' se eu confiar neste comando. Então funciona bem.

michael xie
fonte