Como executo um programa do Python? os.system falha devido a espaços no caminho

273

Eu tenho um script Python que precisa executar um programa externo, mas por algum motivo falha.

Se eu tiver o seguinte script:

import os;
os.system("C:\\Temp\\a b c\\Notepad.exe");
raw_input();

Em seguida, falha com o seguinte erro:

'C: \ Temp \ a' não é reconhecido como um comando interno ou externo, programa operável ou arquivo em lote.

Se eu escapar do programa com aspas:

import os;
os.system('"C:\\Temp\\a b c\\Notepad.exe"');
raw_input();

Então funciona. No entanto, se eu adicionar um parâmetro, ele deixará de funcionar novamente:

import os;
os.system('"C:\\Temp\\a b c\\Notepad.exe" "C:\\test.txt"');
raw_input();

Qual é a maneira correta de executar um programa e esperar que ele seja concluído? Não preciso ler a saída dele, pois é um programa visual que faz um trabalho e depois sai, mas preciso aguardar a conclusão.

Observe também que mover o programa para um caminho não espaçado também não é uma opção.


Isso também não funciona:

import os;
os.system("'C:\\Temp\\a b c\\Notepad.exe'");
raw_input();

Observe as aspas simples / duplas trocadas.

Com ou sem um parâmetro para o Bloco de Notas aqui, ele falha com a mensagem de erro

O nome do arquivo, nome do diretório ou sintaxe do rótulo do volume está incorreto.

Lasse V. Karlsen
fonte
Utilize este: os.system(r'C:\temp\"a b c"\Notepad.exe') ou esta:os.system('C:\\temp\\"a b c"\\Notepad.exe')
chanzerre
Para futuros visitantes, se você deseja executar um aplicativo com argumentos (usando o subprocesso). você precisa dividir seus argumentos por espaço e passar cada um individualmente. Por exemplo, esta é a partir de um arquivo bat: "C:\Program Files\GDAL\gdal_translate.exe" -ot byte -of GTIFF -scale -co PHOTOMETRIC=CMYK "cmyk-16.tif" "cmyk-8_out.tif". Em Python, torna-se: ["C:\\Program Files\\GDAL\\gdal_translate.exe", "-ot", "byte", "-scale", "-co", "PHOTOMETRIC=CMYK", "input_cmyk-16.tif", "output_cmyk-8.tif"].
akinuri

Respostas:

297

subprocess.callevitará problemas em ter que lidar com convenções de cotação de várias conchas. Ele aceita uma lista, em vez de uma sequência, para que os argumentos sejam mais facilmente delimitados. ie

import subprocess
subprocess.call(['C:\\Temp\\a b c\\Notepad.exe', 'C:\\test.txt'])
Brian
fonte
81
É muito mais simples usar a string bruta no Windows: r "C: \ Temp \ abc \ Notepad.exe"
PierreBdR 15/10/08
1
Sim, as funções os.exec * substituirão o processo atual, portanto seu processo python não continuará. Eles são usados ​​mais no unix, onde o método geral para um shell iniciar um comando é fork () e, em seguida, exec () no filho.
18711 Brian
1
O método windows para isso é a família os.spawn, que poderia ser usada em seu lugar. O subprocesso é mais portátil, porém, e oferece mais flexibilidade no controle do processo (captura de entrada / saída, etc.), então é preferível.
18711 Brian
6
@PierreBdr: Há um caso em que as strings não funcionam: onde você precisa de uma barra final. por exemplo, r'c: \ foo \ bar \ '. Na verdade, é provavelmente melhor usar barras dianteiras. Estes são aceitos em todo o API do Windows (embora nem sempre por alguns comandos shell (por exemplo, cópia))
Brian
1
Para python> = 3.5 subprocess.calldeve ser substituído por subprocess.run docs.python.org/3/library/subprocess.html#older-high-level-api
gbonetti
67

Aqui está uma maneira diferente de fazer isso.

Se você estiver usando o Windows, as seguintes ações funcionam como clicar duas vezes no arquivo no Explorer ou fornecer o nome do arquivo como argumento para o comando "start" do DOS: o arquivo é aberto com qualquer aplicativo (se houver) ao qual sua extensão está associada .

filepath = 'textfile.txt'
import os
os.startfile(filepath)

Exemplo:

import os
os.startfile('textfile.txt')

Isso abrirá o textfile.txt com o Bloco de Notas se o Bloco de Notas estiver associado aos arquivos .txt.

user16738
fonte
1
Existe uma função equivalente para sistemas * nix?
Romeno
@ Romomen: você pode tentar: webbrowser.open("textfile.txt")ele deve abrir um editor de texto. Veja também "inicie o segundo programa por si só, como se eu tivesse apenas 'clicado duas vezes nele'".
JFS
Na minha configuração, o textfile.txt precisa estar entre aspas, por exemplo:os.startfile('path\to\textfile.txt')
thdoan
34

As aspas mais externas são consumidas pelo próprio Python e o shell do Windows não o vê. Como mencionado acima, o Windows entende apenas aspas duplas. O Python converterá barras invertidas em barras invertidas no Windows, para que você possa usar

os.system('"C://Temp/a b c/Notepad.exe"')

O 'é consumido pelo Python, que passa "C: //Temp/abc/Notepad.exe" (como um caminho do Windows, não são necessárias duas barras invertidas) para o CMD.EXE

Daniel Serodio
fonte
1
Isso parece o melhor em um cenário como o os.system('curl URL > file')local em que eu quero ver a atualização do medidor de progresso do cURL para arquivos realmente grandes.
Zach Young
Se a primeira letra após uma barra invertida tem um significado especial (ou seja \t, \n, etc.), então, que determinado barra invertida deve ser duplicada. Ser um caminho do Windows não tem nada a ver com isso.
Ethan Furman
1
Observe que, se você usar os.system()no Windows, a janela cmd será aberta e permanecerá aberta até você fechar o processo iniciado. IMHO é melhor usar os.startfile().
thdoan
1
Não se esqueçaimport os
Besi
não funciona para mim stackoverflow.com/questions/56241616/…
Gulzar #
19

Pelo menos no Windows 7 e Python 3.1, os.systemno Windows deseja que a linha de comando entre aspas duplas se houver espaços no caminho para o comando. Por exemplo:

  TheCommand = '\"\"C:\\Temp\\a b c\\Notepad.exe\"\"'
  os.system(TheCommand)

Um exemplo do mundo real que estava me surpreendendo foi a clonagem de uma unidade no VirtualBox. A subprocess.callsolução acima não funcionou devido a algum problema de direitos de acesso, mas quando citei duas vezes o comando, os.systemfiquei feliz:

  TheCommand = '\"\"C:\\Program Files\\Sun\\VirtualBox\\VBoxManage.exe\" ' \
                 + ' clonehd \"' + OrigFile + '\" \"' + NewFile + '\"\"'
  os.system(TheCommand)
Paul Hoffman
fonte
Foi isso! Eu iria para subprocess, mas às vezes os.systeme os.popen(...).read()são apenas mais rápidos para digitar. BTW, você não precisa escapar de aspas duplas em single, ou seja '""C:\\Temp\\a b c\\Notepad.exe""', fará.
Tomasz Gandor
9
import win32api # if active state python is installed or install pywin32 package seperately

try: win32api.WinExec('NOTEPAD.exe') # Works seamlessly
except: pass
rahul
fonte
e parece que nenhuma citação é necessária com esse método, por exemplo, win32api.WinExec ('pythonw.exe d: \ web2py \ web2py.py -K welcome') inicia o programador web2py em segundo plano.
22412 Tim
@rahul, exceto argumentos para o executável? Então, se você deseja que o Bloco de notas abra um arquivo ou é separado?
sayth
3

Eu suspeito que é o mesmo problema que quando você usa atalhos no Windows ... Tente o seguinte:

import os;
os.system("\"C:\\Temp\\a b c\\Notepad.exe\" C:\\test.txt");
Matthew Scharley
fonte
desculpe, isso também não funciona, pergunta editada para refletir isso.
Lasse V. Karlsen
Acho que o Windows usa apenas ", em vez de 'para citar. Isso provavelmente funcionará se você alterar isso. No entanto, você ainda terá problemas se tiver aspas incorporadas etc.
Brian
Eu pensei que foram necessários os dois, mas você provavelmente está certo. Eu sei que funciona (no shell pelo menos) com aspas duplas.
Matthew Scharley 15/10/08
+1 este é o melhor, o Windows XP, 2007 home edition funcionou bem #
0

Suponha que desejamos executar o servidor da web do Django (no Linux) que exista espaço entre o seu caminho (path = '/home/<you>/<first-path-section> <second-path-section>'), faça o seguinte:

import subprocess

args = ['{}/manage.py'.format('/home/<you>/<first-path-section> <second-path-section>'), 'runserver']
res = subprocess.Popen(args, stdout=subprocess.PIPE)
output, error_ = res.communicate()

if not error_:
    print(output)
else:
    print(error_)

[ Nota ]:

  • Não se esqueça de acessar a permissão: chmod 755 -R <'yor path'>
  • manage.py é excedable: chmod +x manage.py
Benyamin Jafari
fonte
0

Para Python 3.7, use subprocess.call . Use a sequência bruta para simplificar os caminhos do Windows:

import subprocess
subprocess.call([r'C:\Temp\Example\Notepad.exe', 'C:\test.txt'])
WestAce
fonte
0

Não há necessidade de subprocesso, pode ser alcançado simplesmente por

GitPath = "C: \ Arquivos de programas \ Git \ git-bash.exe" # Caminho do arquivo do aplicativo no mycase, seu GITBASH os.startfile (GitPath)

rajat prakash
fonte