Python subprocess
O terminal da Ana tem centenas de programas prontos: ls lista arquivos, grep procura texto, sqlite3 abre bancos de dados, git guarda versões. Às vezes, o jeito mais rápido de um programa Python fazer alguma coisa é pedir a um desses programas que faça. O módulo subprocess ("subprocesso", um processo filho) serve para isso: rodar outro programa, esperar ele terminar, saber se deu certo e pegar o que ele escreveu.
- A rodar um programa com
subprocess.run, passando o comando como uma lista. - A ler o código de saída com
returncode. - A pegar o que o programa escreveu com
capture_output=Trueetext=True. - A fazer o Python reclamar quando o comando falha, com
check=True, e a ler oCalledProcessError. - A pôr um limite de tempo (
timeout), mandar dados para o programa (input) e montar a lista comshlex.split. - Quando (quase nunca) usar
shell=True, e os erros reais: programa que não existe, comando como texto, ogrepque "falha" sem falhar.
O subprocess chama programas do seu computador. O editor do guia roda o Python dentro do navegador, onde não existem ls, grep nem outros programas para chamar: lá o subprocess não funciona. Por isso os exemplos desta aula aparecem em janelas de terminal, com o que o Ubuntu da Ana respondeu de verdade, e as caixas "Experimente" treinam só a parte que é Python puro: montar a lista do comando e interpretar a resposta. Para rodar os exemplos, crie os arquivos no seu computador e use python3 arquivo.py (aula Rodando um Programa).
A ideia: pedir um serviço a um colega
A Ana não faz tudo sozinha na padaria. Quando precisa de um bolo de casamento, ela liga para a Dona Rosa, que é especialista: diz exatamente o que quer ("bolo, três andares, de coco"), espera ficar pronto e recebe duas coisas de volta: o bolo e um "deu tudo certo" (ou "faltou coco, não deu"). Ela não precisa saber como a Dona Rosa trabalha.
| Na padaria | No subprocess |
|---|---|
| Ligar para a Dona Rosa | subprocess.run(…) |
| O pedido, item por item | A lista do comando: ["ls", "-1"] |
| Esperar ficar pronto | O run espera o programa terminar |
| O bolo que volta | O que o programa escreveu: stdout |
| "Deu certo" ou "não deu" | O código de saída: returncode (0 = deu certo) |
| O bilhete de reclamação | A saída de erros: stderr |
Nos exemplos, a Ana está na pasta da lojinha, que tem estes arquivos (e os .py que ela vai criando):
farinha,12 ovos,0 leite,5 acucar,0
1. O primeiro subprocess.run
import subprocess
resultado = subprocess.run(["ls", "-1"])
print("Terminou com o código", resultado.returncode)
$ python3 rodar1.py clientes.json estoque.csv rodar1.py vendas.py Terminou com o código 0
- import subprocess
- O módulo vem com o Python.
- subprocess.run(…)
- "Rode": inicia o programa, espera ele terminar e só depois segue para a linha de baixo.
- ["ls", "-1"]
- O comando, como uma lista de textos: o nome do programa e cada argumento num item separado. É o mesmo que digitar
ls -1no terminal (o-1pede um nome por linha). - resultado
- O
rundevolve um objetoCompletedProcess("processo concluído") com tudo o que aconteceu. - resultado.returncode
- O código de saída do programa: 0 é "deu certo" (aula Os Módulos os e sys).
Os nomes dos arquivos apareceram na tela porque, por padrão, o programa chamado escreve direto no mesmo terminal do Python. O seu programa não "viu" esses nomes: só ficou sabendo do código 0. Para pegar o que o programa escreveu, é preciso pedir.
2. Pegando a saída: capture_output=True e text=True
import subprocess resultado = subprocess.run(["ls", "-1"], capture_output=True) print(resultado.stdout)
$ python3 rodar2.py b'clientes.json\nestoque.csv\nrodar1.py\nrodar2.py\nvendas.py\n'
Com capture_output=True ("capturar a saída"), nada foi para a tela: o que o ls escreveu ficou guardado em resultado.stdout. Mas veio estranho: um b na frente e os \n à mostra. É um valor do tipo bytes, os bytes crus que o programa mandou, ainda sem virar texto. Para receber um texto normal (str), acrescente text=True:
import subprocess
resultado = subprocess.run(["ls", "-1"], capture_output=True, text=True)
print(repr(resultado.stdout))
arquivos = resultado.stdout.splitlines()
print("São", len(arquivos), "arquivos:", arquivos)
$ python3 rodar3.py 'clientes.json\nestoque.csv\nrodar1.py\nrodar2.py\nrodar3.py\nvendas.py\n' São 6 arquivos: ['clientes.json', 'estoque.csv', 'rodar1.py', 'rodar2.py', 'rodar3.py', 'vendas.py']
- capture_output=True
- Guarda a saída normal em
resultado.stdoute a de erros emresultado.stderr, em vez de mostrar na tela. - text=True
- Converte os bytes em texto (
str), usando a codificação do sistema (UTF-8 na Ana). Agora dá para usar os métodos de texto. - .splitlines()
- Quebra o texto numa lista, uma linha por item (aula Métodos de Texto).
Um exemplo mais útil: quais produtos acabaram? O grep procura as linhas que terminam em ,0 (o $, para o grep, quer dizer "fim da linha"):
import subprocess
resultado = subprocess.run(
["grep", ",0$", "estoque.csv"],
capture_output=True,
text=True,
)
print("Código:", resultado.returncode)
print("Acabaram:")
print(resultado.stdout, end="")
$ python3 zerados.py Código: 0 Acabaram: ovos,0 acucar,0
Repare na lista: ",0$" foi escrito sem aspas extras. No terminal, você digitaria grep ',0$' estoque.csv, com as aspas simples para o terminal não mexer no $. Na lista do subprocess não tem terminal no meio: cada item já chega ao programa exatamente como está.
Ler um arquivo e procurar linhas, o Python faz sozinho (aula Lendo Arquivos), sem depender de o grep existir no computador. O subprocess vale a pena quando o programa de fora faz algo que o Python não faz fácil: o git, um conversor de vídeo, o sqlite3, um script de outra pessoa.
3. Quando o comando dá errado: returncode e stderr
A pasta fotos não existe. O que o subprocess conta quando o ls falha?
import subprocess
resultado = subprocess.run(["ls", "fotos"], capture_output=True, text=True)
print("Código:", resultado.returncode)
print("stdout:", repr(resultado.stdout))
print("stderr:", repr(resultado.stderr))
$ python3 falha.py Código: 2 stdout: '' stderr: "ls: não é possível acessar 'fotos': Arquivo ou diretório inexistente\n"
Nenhum erro do Python! O run fez a parte dele: rodou o ls e trouxe a resposta. Quem falhou foi o ls, e ele avisou do jeito dos programas de terminal: código 2 (diferente de zero) e a mensagem na saída de erros (stderr), em português, porque o ls segue o idioma do sistema. A saída normal veio vazia.
Se você não olhar o returncode, o seu programa segue em frente como se tudo tivesse dado certo. É o erro mais comum com subprocess. Ou confira o código, ou use o check=True, logo abaixo.
4. check=True: falhou, para tudo
Com check=True ("conferir"), o próprio run olha o código de saída. Se não for 0, ele lança uma exceção, a CalledProcessError ("erro do processo chamado"):
import subprocess
subprocess.run(["ls", "fotos"], check=True)
print("Esta linha não roda.")
$ python3 falha2.py
ls: não é possível acessar 'fotos': Arquivo ou diretório inexistente
Traceback (most recent call last):
File "/home/ana/loja/falha2.py", line 3, in <module>
subprocess.run(["ls", "fotos"], check=True)
~~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/usr/lib/python3.14/subprocess.py", line 578, in run
raise CalledProcessError(retcode, process.args,
output=stdout, stderr=stderr)
subprocess.CalledProcessError: Command '['ls', 'fotos']' returned non-zero exit status 2.
$ echo $?
1
Leia por partes, de cima para baixo:
- ls: não é possível acessar 'fotos'…
- A mensagem do próprio
ls. Semcapture_output, ela foi direto para a tela. - Traceback (most recent call last):
- Começa a mensagem de erro do Python.
- File "/home/ana/loja/falha2.py", line 3
- A linha do seu programa: o
subprocess.runda linha 3. - File "/usr/lib/python3.14/subprocess.py", line 578, in run
- Uma linha de dentro do módulo
subprocess: é lá que fica oraise CalledProcessError(...)que lançou o erro. Você não mexe nesse arquivo; a causa está na sua linha. - subprocess.CalledProcessError
- O tipo da exceção. Ela mora dentro do módulo, por isso o nome completo é
subprocess.CalledProcessError. - Command '['ls', 'fotos']' returned non-zero exit status 2.
- "O comando
['ls', 'fotos']devolveu o código de saída 2, diferente de zero". - echo $?
- O Python terminou com 1, como em toda exceção não tratada. O
printda linha 4 não rodou.
Tratando o erro com try
Uma exceção se trata com try e except (aula try e except). O objeto do erro traz o comando, o código e, se você capturou a saída, a mensagem:
import subprocess
try:
subprocess.run(["ls", "fotos"], capture_output=True, text=True, check=True)
except subprocess.CalledProcessError as erro:
print("O comando falhou!")
print("Comando:", erro.cmd)
print("Código:", erro.returncode)
print("Mensagem:", erro.stderr.strip())
$ python3 falha3.py O comando falhou! Comando: ['ls', 'fotos'] Código: 2 Mensagem: ls: não é possível acessar 'fotos': Arquivo ou diretório inexistente
| Atributo | No CompletedProcess (resultado) | No CalledProcessError (erro) |
|---|---|---|
| O comando | resultado.args | erro.cmd |
| O código de saída | resultado.returncode | erro.returncode |
| A saída normal | resultado.stdout | erro.stdout |
| A saída de erros | resultado.stderr | erro.stderr |
(stdout e stderr só têm conteúdo com capture_output=True; sem ele, valem None.)
5. Mais três opções: timeout, input e sys.executable
timeout: não esperar para sempre
O run espera o programa terminar. E se ele travar? timeout=2 diz "espere no máximo 2 segundos". O sleep 10 abaixo é um programa que só fica parado 10 segundos:
import subprocess subprocess.run(["sleep", "10"], timeout=2)
$ python3 demora.py
Traceback (most recent call last):
File "/home/ana/loja/demora.py", line 3, in <module>
subprocess.run(["sleep", "10"], timeout=2)
~~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/usr/lib/python3.14/subprocess.py", line 557, in run
stdout, stderr = process.communicate(input, timeout=timeout)
~~~~~~~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^
File "/usr/lib/python3.14/subprocess.py", line 1221, in communicate
stdout, stderr = self._communicate(input, endtime, timeout)
~~~~~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^^
File "/usr/lib/python3.14/subprocess.py", line 2179, in _communicate
self.wait(timeout=self._remaining_time(endtime))
~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/usr/lib/python3.14/subprocess.py", line 1279, in wait
return self._wait(timeout=timeout)
~~~~~~~~~~^^^^^^^^^^^^^^^^^
File "/usr/lib/python3.14/subprocess.py", line 2076, in _wait
raise TimeoutExpired(self.args, timeout)
subprocess.TimeoutExpired: Command '['sleep', '10']' timed out after 2 seconds
O traceback é comprido, mas segue a regra de sempre: a primeira linha File é a sua (linha 3 do demora.py); as outras são o caminho por dentro do módulo; a última diz o que houve. TimeoutExpired: "o tempo acabou", depois de 2 segundos. O run encerra o programa atrasado antes de lançar o erro. Dá para tratar com except subprocess.TimeoutExpired:.
input e sys.executable: conversar com outro programa Python
Um programa pode receber dados pela entrada padrão (o "teclado" dele). A Ana tem um soma.py que lê linhas do estoque e soma as quantidades:
import sys
total = 0
for linha in sys.stdin:
total += int(linha.split(",")[1])
print("Itens no estoque:", total)
E outro programa que chama o soma.py, mandando o conteúdo do arquivo como se alguém tivesse digitado:
import subprocess
import sys
with open("estoque.csv", encoding="utf-8") as arquivo:
conteudo = arquivo.read()
resultado = subprocess.run(
[sys.executable, "soma.py"],
input=conteudo,
capture_output=True,
text=True,
check=True,
)
print("O soma.py respondeu:", resultado.stdout.strip())
$ python3 chama_python.py O soma.py respondeu: Itens no estoque: 17
- sys.executable
- O caminho do Python que está rodando agora (aula os e sys). Melhor que escrever
"python3": se você estiver num ambiente virtual, o filho usa o mesmo Python, com os mesmos pacotes. - input=conteudo
- O texto que o programa filho vai ler na entrada padrão (com
text=True, umstr). - check=True
- Se o
soma.pyquebrar, o pai fica sabendo na hora.
(12 + 0 + 5 + 0 = 17.) Na vida real, para usar o código de outro arquivo Python, o normal é importar (aula Criando seu Módulo). Chamar com subprocess faz sentido quando o outro programa precisa rodar separado, como um programa à parte.
6. Montando a lista: shlex.split e o shell=True
Escrever ["grep", ",0$", "estoque.csv"] à mão cansa. Se você já tem o comando do jeito que digitaria no terminal, o módulo shlex (de shell lexer, "separador do terminal") quebra o texto do mesmo jeito que o terminal quebraria, respeitando as aspas:
import shlex
print(shlex.split("grep -c ',0$' estoque.csv"))
print(shlex.split('ls -l "Área de trabalho"'))
$ python3 dividir.py ['grep', '-c', ',0$', 'estoque.csv'] ['ls', '-l', 'Área de trabalho']
As aspas sumiram e "Área de trabalho" ficou num item só, como o terminal faria. Um simples .split() quebraria nos espaços e erraria. O shlex é Python puro, então dá para treinar aqui:
Missão: o .split() quebrou "Área de trabalho" em três pedaços, e as aspas vieram junto. Troque por shlex.split(comando) para a lista sair ['ls', '-l', 'Área de trabalho'], pronta para o subprocess.run.
import shlex comando = 'ls -l "Área de trabalho"' partes = comando.split() print(partes) print(len(partes), "partes")
import shlex comando = 'ls -l "Área de trabalho"' partes = shlex.split(comando) print(partes) print(len(partes), "partes")
shell=True: deixar o terminal interpretar
Com shell=True, você passa um texto, e quem lê é um terminal (o /bin/sh), com todos os poderes dele: *, |, >…
import subprocess
resultado = subprocess.run("ls *.csv | wc -l", shell=True, capture_output=True, text=True)
print("Arquivos .csv:", resultado.stdout.strip())
$ python3 concha.py Arquivos .csv: 1
shell=True com dados de fora
Se uma parte do texto vier do usuário (um input(), um argumento, um nome de arquivo), alguém pode escrever bolo; rm -rf ~, e o terminal vai obedecer aos dois comandos: o ; separa comandos. Com a lista, isso não acontece: "bolo; rm -rf ~" chega ao programa como um argumento só, um nome estranho, e nada mais. Prefira sempre a lista; use shell=True só com textos fixos, escritos por você, quando precisar mesmo de | ou *.
Formas diferentes de rodar um comando
| Jeito | Quando usar |
|---|---|
subprocess.run([...]) | Só rodar e deixar a saída ir para a tela |
subprocess.run([...], capture_output=True, text=True) | Você quer ler o que o programa respondeu |
… check=True | Quase sempre: falhou, você fica sabendo |
… timeout=N | O programa pode travar (rede, programa de outra pessoa) |
subprocess.run("…", shell=True) | Só com texto fixo e quando precisa de |, *, > |
os.system("…") | Evite: é a forma antiga, com os riscos do shell=True e sem como pegar a saída |
| Fazer em Python mesmo | Sempre que der: ler arquivos, listar pastas (os.listdir), copiar (shutil). Funciona em qualquer sistema |
Quando dá errado
FileNotFoundError
import subprocess subprocess.run(["lss", "-1"])
$ python3 errado1.py
Traceback (most recent call last):
File "/home/ana/loja/errado1.py", line 3, in <module>
subprocess.run(["lss", "-1"])
~~~~~~~~~~~~~~^^^^^^^^^^^^^^^
File "/usr/lib/python3.14/subprocess.py", line 555, in run
with Popen(*popenargs, **kwargs) as process:
~~~~~^^^^^^^^^^^^^^^^^^^^^^
File "/usr/lib/python3.14/subprocess.py", line 1039, in __init__
self._execute_child(args, executable, preexec_fn, close_fds,
~~~~~~~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
pass_fds, cwd, env,
^^^^^^^^^^^^^^^^^^^
...<5 lines>...
gid, gids, uid, umask,
^^^^^^^^^^^^^^^^^^^^^^
start_new_session, process_group)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/usr/lib/python3.14/subprocess.py", line 1990, in _execute_child
raise child_exception_type(errno_num, err_msg, err_filename)
FileNotFoundError: [Errno 2] No such file or directory: 'lss'
Diferente do ls fotos: ali o ls rodou e falhou (código 2). Aqui, o programa lss nem existe, então não há código de saída nenhum, e o Python lança FileNotFoundError ("arquivo não encontrado") com o nome que ele procurou: 'lss'. O ...<5 lines>... é o Python resumindo um trecho comprido do código interno. Como consertar: confira o nome do programa (ls) e se ele está instalado (which ls no terminal).
shell=True
import subprocess
subprocess.run("ls -1")
$ python3 errado2.py
Traceback (most recent call last):
File "/home/ana/loja/errado2.py", line 3, in <module>
subprocess.run("ls -1")
~~~~~~~~~~~~~~^^^^^^^^^
File "/usr/lib/python3.14/subprocess.py", line 555, in run
with Popen(*popenargs, **kwargs) as process:
~~~~~^^^^^^^^^^^^^^^^^^^^^^
File "/usr/lib/python3.14/subprocess.py", line 1039, in __init__
self._execute_child(args, executable, preexec_fn, close_fds,
~~~~~~~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
pass_fds, cwd, env,
^^^^^^^^^^^^^^^^^^^
...<5 lines>...
gid, gids, uid, umask,
^^^^^^^^^^^^^^^^^^^^^^
start_new_session, process_group)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/usr/lib/python3.14/subprocess.py", line 1990, in _execute_child
raise child_exception_type(errno_num, err_msg, err_filename)
FileNotFoundError: [Errno 2] No such file or directory: 'ls -1'
Olhe o nome no fim: 'ls -1', com o espaço. Sem terminal no meio, ninguém separou o texto, e o Python procurou um programa chamado, literalmente, "ls espaço traço um". Como consertar: passe a lista, ["ls", "-1"] (ou shlex.split("ls -1")).
grep
import subprocess
resultado = subprocess.run(["grep", "chocolate", "estoque.csv"], capture_output=True, text=True)
print("Código:", resultado.returncode)
print("Achou:", repr(resultado.stdout))
$ python3 nada.py Código: 1 Achou: ''
Nenhuma linha tem "chocolate", e o grep respondeu com o código 1. Para o grep, 1 não é falha: quer dizer "procurei e não achei" (o erro de verdade, como arquivo inexistente, é o 2). Se esse run tivesse check=True, um simples "não achei" virava CalledProcessError. Como lidar: leia a documentação do programa (man grep, no fim, explica os códigos) e, nesses casos, confira o returncode você mesmo, sem check=True.
text=True
Você viu na seção 2: sem text=True, a saída vem como bytes (b'clientes.json\n…'), e métodos como .splitlines() devolvem bytes também; juntar com um texto normal dá TypeError. Como consertar: acrescente text=True.
Rodar subprocess no "Experimente" não funciona: o Python do navegador não tem outros programas para chamar. O mesmo subprocess.run(["ls", "-1"]), numa caixa do editor, termina assim:
$ python3 main.py
Traceback (most recent call last):
File "/home/ana/main.py", line 3, in <module>
subprocess.run(["ls", "-1"])
~~~~~~~~~~~~~~^^^^^^^^^^^^^^
File "/usr/lib/python3.14/subprocess.py", line 554, in run
with Popen(*popenargs, **kwargs) as process:
~~~~~^^^^^^^^^^^^^^^^^^^^^^
File "/usr/lib/python3.14/subprocess.py", line 827, in __init__
raise OSError(
errno.ENOTSUP, f"{sys.platform} does not support processes."
)
OSError: [Errno 138] emscripten does not support processes.
"O emscripten não tem processos": emscripten é a ferramenta que levou o Python para dentro do navegador, e lá não existe como iniciar outro programa. Não é erro no seu código. Rode esses exemplos no terminal do seu computador.
Para fechar: a parte de interpretar a resposta é Python puro, e é onde moram os erros mais sutis. A missão final treina isso com respostas que o grep poderia dar.
Referência rápida
| Código | O que faz |
|---|---|
subprocess.run(["prog", "arg1", "arg2"]) | Roda o programa e espera terminar |
resultado.returncode | Código de saída (0 = deu certo) |
capture_output=True | Guarda as saídas em .stdout e .stderr |
text=True | Saídas (e input) como texto, não bytes |
check=True | Código diferente de 0 vira subprocess.CalledProcessError |
timeout=N | Mais de N segundos vira subprocess.TimeoutExpired |
input="…" | Manda o texto para a entrada padrão do programa |
cwd="pasta" | Roda o programa dentro de outra pasta |
[sys.executable, "outro.py"] | Roda outro script com o mesmo Python |
shlex.split("cmd 'a b'") | Texto → lista, como o terminal separaria |
shell=True | Passa um texto para o /bin/sh interpretar (cuidado) |
| Sintoma | Causa provável |
|---|---|
FileNotFoundError: … 'lss' | O programa não existe ou o nome está errado |
FileNotFoundError: … 'ls -1' (com espaço) | Comando passado como texto: use a lista |
CalledProcessError: … returned non-zero exit status N | Com check=True, o programa terminou com código N |
TimeoutExpired: … timed out after N seconds | Passou do timeout |
A saída começa com b' | Faltou text=True |
resultado.stdout é None | Faltou capture_output=True |
| O programa falhou e o Python seguiu como se nada fosse | Ninguém olhou o returncode (ou faltou check=True) |
Exercícios
1. Pegar a saída como texto
Complete as duas opções que fazem a saída do ls ficar em resultado.stdout, como texto:
2. O código de saída
Qual atributo do resultado guarda o código de saída?
3. A exceção do check=True
Complete o except:
4. Qual destas chamadas roda grep -c ovos estoque.csv do jeito recomendado?
5. Sem check=True, o ls fotos falha (a pasta não existe). O que acontece no programa Python?
6. Por que evitar shell=True com um nome que o usuário digitou?
Missão final: entender a resposta do grep
Missão: a função interpretar recebe o returncode e o stdout de um grep ",0$" estoque.csv. Complete: código 0 → Acabaram: e os nomes dos produtos (o que vem antes da vírgula em cada linha), separados por vírgula; código 1 → Nada acabou.; qualquer outro → Erro no grep (código N)..
def interpretar(codigo, saida):
print("Código recebido:", codigo)
interpretar(0, "ovos,0\nacucar,0\n")
interpretar(1, "")
interpretar(2, "")
def interpretar(codigo, saida):
if codigo == 0:
nomes = []
for linha in saida.splitlines():
nomes.append(linha.split(",")[0])
print("Acabaram:", ", ".join(nomes))
elif codigo == 1:
print("Nada acabou.")
else:
print(f"Erro no grep (código {codigo}).")
interpretar(0, "ovos,0\nacucar,0\n")
interpretar(1, "")
interpretar(2, "")
No seu computador, troque as chamadas de teste por um subprocess.run(["grep", ",0$", "estoque.csv"], capture_output=True, text=True) e passe resultado.returncode e resultado.stdout para a função.
Resumo
subprocess.run(["programa", "arg"])roda outro programa e espera ele terminar. Passe o comando como lista.returncodeé o código de saída: 0 deu certo; outro número, problema (ou, como nogrep, "não achei").capture_output=Trueguarda a saída em.stdout/.stderr;text=Truefaz dela um texto.check=Truetransforma falha emsubprocess.CalledProcessError, que se trata comtry/except.timeoutlimita a espera (TimeoutExpired);inputmanda dados;sys.executablechama outro script com o mesmo Python.shlex.splitmonta a lista a partir do texto;shell=Truesó com texto fixo, nunca com dados do usuário.- Programa inexistente (ou comando como texto):
FileNotFoundError. No editor do guia, osubprocessnão funciona: use o terminal.