Existem quatro casos fortes para preferir os métodos mais específicos do Python no os
módulo ao invés de usar os.system
ou no subprocess
módulo ao executar um comando:
- Redundância - gerar outro processo é redundante e desperdiça tempo e recursos.
- Portabilidade - Muitos dos métodos do
os
módulo estão disponíveis em várias plataformas, enquanto muitos comandos do shell são específicos do sistema operacional.
- Entendendo os resultados - Gerar um processo para executar comandos arbitrários obriga a analisar os resultados da saída e entender se e por que um comando fez algo errado.
- Segurança - Um processo pode potencialmente executar qualquer comando fornecido. Esse é um design fraco e pode ser evitado usando métodos específicos no
os
módulo.
Na verdade, você está executando um "intermediário" redundante no caminho para as eventuais chamadas do sistema ( chmod
no seu exemplo). Esse intermediário é um novo processo ou sub-shell.
De os.system
:
Execute o comando (uma string) em um subshell ...
E subprocess
é apenas um módulo para gerar novos processos.
Você pode fazer o que precisa sem gerar esses processos.
O os
objetivo do módulo é fornecer serviços genéricos de sistema operacional e sua descrição começa com:
Este módulo fornece uma maneira portátil de usar a funcionalidade dependente do sistema operacional.
Você pode usar os.listdir
no Windows e no Unix. Tentar usar os.system
/ subprocess
para esta funcionalidade forçará você a manter duas chamadas (para ls
/ dir
) e verificar em qual sistema operacional você está. Isto não é tão portátil e vai causar ainda mais frustração mais tarde (ver saída Handling ).
Compreendendo os resultados do comando:
Suponha que você queira listar os arquivos em um diretório.
Se você estiver usando os.system("ls")
/ subprocess.call(['ls'])
, poderá recuperar a saída do processo, que é basicamente uma grande string com os nomes dos arquivos.
Como você pode distinguir um arquivo com um espaço no nome de dois arquivos?
E se você não tiver permissão para listar os arquivos?
Como você deve mapear os dados para objetos python?
Isso está fora da minha cabeça e, embora haja soluções para esses problemas - por que resolver novamente um problema que foi resolvido para você?
Este é um exemplo de seguir o princípio Não se repita (geralmente chamado de "SECO") por não repetir uma implementação que já existe e está disponível gratuitamente para você.
Segurança:
os.system
e subprocess
são poderosos. É bom quando você precisa desse poder, mas é perigoso quando não precisa. Quando você usa os.listdir
, sabe que não pode fazer mais nada além de listar arquivos ou gerar um erro. Quando você usa os.system
ou subprocess
obtém o mesmo comportamento, pode acabar fazendo algo que não pretendia fazer.
Segurança de injeção (veja exemplos de injeção de casca ) :
Se você usa a entrada do usuário como um novo comando, basicamente dá a ele um shell. É muito parecido com a injeção de SQL, fornecendo um shell no banco de dados para o usuário.
Um exemplo seria um comando do formulário:
# ... read some user input
os.system(user_input + " some continutation")
Isso pode ser facilmente explorado para executar qualquer código arbitrário usando a entrada: NASTY COMMAND;#
para criar o eventual:
os.system("NASTY COMMAND; # some continuation")
Existem muitos desses comandos que podem colocar seu sistema em risco.