Preciso abrir um documento usando seu aplicativo padrão no Windows e Mac OS. Basicamente, quero fazer o mesmo que acontece quando você clica duas vezes no ícone do documento no Explorer ou no Finder. Qual é a melhor maneira de fazer isso no Python?
125
Respostas:
open
estart
são coisas de interpretador de comandos para Mac OS / X e Windows, respectivamente, para fazer isso.Para chamá-los do Python, você pode usar
subprocess
module ouos.system()
.Aqui estão algumas considerações sobre qual pacote usar:
Você pode chamá-los via
os.system
, o que funciona, mas ...Escapando:
os.system
funciona apenas com nomes de arquivos que não possuem espaços ou outros metacaracteres de shell no nome do caminho (por exemploA:\abc\def\a.txt
), ou eles precisam ser escapados. Existeshlex.quote
para sistemas tipo Unix, mas nada realmente padrão para o Windows. Talvez veja também python, windows: analisando linhas de comando com shlexos.system("open " + shlex.quote(filename))
os.system("start " + filename)
onde se fala corretamente tambémfilename
deve ser evitado.Você também pode chamá-los via
subprocess
módulo, mas ...Para Python 2.7 e mais recente, basta usar
No Python 3.5+, você pode usar de forma equivalente o um pouco mais complexo, mas também um pouco mais versátil
Se você precisar ser compatível desde o Python 2.4, poderá usar
subprocess.call()
e implementar sua própria verificação de erro:Agora, quais são as vantagens de usar
subprocess
?'filename ; rm -rf /'
" e, se o nome do arquivo puder ser corrompido, o uso desubprocess.call
uma proteção adicional é reduzida.retcode
dois casos; mas o comportamento de gerar uma exceção explicitamente no caso de um erro certamente o ajudará a perceber se houver uma falha (embora em alguns cenários, um retorno de retorno possa não ser mais útil do que simplesmente ignorar o erro).À objeção "Mas
subprocess
é preferível". No entanto,os.system()
não é preterido e, de certa forma, é a ferramenta mais simples para esse trabalho em particular. Conclusão: usaros.system()
é, portanto, também uma resposta correta.Uma desvantagem acentuada é que o
start
comando do Windows exige que você passe, oshell=True
que nega a maioria dos benefícios do usosubprocess
.fonte
filename
vem a forma, este é um exemplo perfeito de por que o os.system () é inseguro e ruim. subprocesso é melhor.os.system()
é que ele usa o shell (e você não está escapando aqui, então Bad Things acontecerá para nomes de arquivos perfeitamente válidos que contenham meta-caracteres do shell). O motivo pelo qualsubprocess.call()
é preferido é que você tem a opção de ignorar o shell usandosubprocess.call(["open", filename])
. Isso funciona para todos os nomes de arquivos válidos e não introduz uma vulnerabilidade de injeção de shell, mesmo para nomes de arquivos não confiáveis.Use o
subprocess
módulo disponível no Python 2.4+, nãoos.system()
, para que você não precise lidar com o escape de shell.Os parênteses duplos são porque
subprocess.call()
deseja uma sequência como seu primeiro argumento, então estamos usando uma tupla aqui. Nos sistemas Linux com Gnome, também existe umgnome-open
comando que faz a mesma coisa, masxdg-open
é o padrão Free Desktop Foundation e funciona em ambientes de desktop Linux.fonte
xdg-open
- linux.die.net/man/1/xdg-openxdg-open test.py
e ele abriu a caixa de diálogo de download do firefox para mim. O que há de errado? Estou no manjaro linux.xdg-open
configuração está confusa, mas isso não é algo que possamos solucionar em um comentário. Talvez veja unix.stackexchange.com/questions/36380/…Eu prefiro:
Observe que este módulo suporta nomes de arquivos com espaços em suas pastas e arquivos, por exemplo
( docs python ) 'open' não precisa ser adicionado (é o padrão). Os documentos mencionam especificamente que isso é como clicar duas vezes no ícone de um arquivo no Windows Explorer.
Esta solução é apenas para Windows.
fonte
startfile
função nem existe, o que significa que os usuários receberão uma mensagem de erro confusa sobre uma função ausente. Você pode querer verificar a plataforma para evitar isso.Apenas para completar (não estava em questão), o xdg-open fará o mesmo no Linux.
fonte
fonte
Se você precisar usar um método heurístico, considere
webbrowser
.É uma biblioteca padrão e, apesar do nome, também tentaria abrir arquivos:
Eu tentei esse código e funcionou bem no Windows 7 e no Ubuntu Natty:
Esse código também funciona bem no Windows XP Professional, usando o Internet Explorer 8.
fonte
open location
lá que deve funcionar se você der o caminho como um URL válido.import webbrowser webbrowser.open("file:///Users/nameGoesHere/Desktop/folder/file.py")
Se você quiser seguir o
subprocess.call()
caminho, deve ficar assim no Windows:Você não pode simplesmente usar:
porque
start
não é um executável, mas um comando docmd.exe
programa. Isso funciona:mas somente se não houver espaços no FILE_NAME.
Enquanto o
subprocess.call
métodoencita os parâmetros corretamente, ostart
comando tem uma sintaxe bastante estranha, onde:faz algo diferente de:
A primeira string entre aspas deve definir o título da janela. Para fazê-lo funcionar com espaços, precisamos fazer:
que é o que o código na parte superior faz.
fonte
O Start não suporta nomes de caminhos longos e espaços em branco. Você precisa convertê-lo em caminhos compatíveis com 8.3.
O arquivo precisa existir para funcionar com a chamada da API.
fonte
start "Title" "C:\long path to\file.avi"
Estou muito atrasado para o lote, mas aqui está uma solução usando a API do Windows. Isso sempre abre o aplicativo associado.
Muitas constantes mágicas. O primeiro zero é o hwnd do programa atual. Pode ser zero. Os outros dois zeros são parâmetros opcionais (parâmetros e diretório). 5 == SW_SHOW, especifica como executar o aplicativo. Leia os documentos da API ShellExecute para obter mais informações.
fonte
os.startfile(file)
?no mac os você pode chamar de 'aberto'
isso abriria o arquivo com o TextEdit ou qualquer aplicativo definido como padrão para esse tipo de arquivo
fonte
Se você deseja especificar o aplicativo para abrir o arquivo no Mac OS X, use este:
os.system("open -a [app name] [file name]")
fonte
No Windows 8.1, abaixo funcionou, enquanto outras formas dadas com
subprocess.call
falha no caminho possuem espaços.Utilizando essas e outras respostas anteriores, aqui está um código embutido que funciona em várias plataformas.
fonte
os.startfile(path, 'open')
no Windows é bom porque, quando existem espaços no diretório,os.system('start', path_name)
não é possível abrir o aplicativo corretamente e quando o i18n existe no diretório, éos.system
necessário alterar o unicode para o codec do console no Windows.fonte