O que é um subprocesso em Python? [5 exemplos de uso]
Publicados: 2021-05-23Os subprocessos permitem que você interaja em um nível totalmente novo com o Sistema Operativo.
Nosso computador executa subprocessos o tempo todo. Na verdade, apenas lendo este artigo, você está executando vários processos, como um gerenciador de rede ou o próprio navegador da Internet.
O legal disso é que qualquer ação que fazemos em nosso computador envolve a invocação de um subprocesso. Isso permanece verdadeiro mesmo que estejamos escrevendo um script “hello world” simples em python.
O conceito de subprocesso pode parecer obscuro, mesmo se você estiver aprendendo programação há algum tempo. Este artigo examinará profundamente o conceito principal do subprocesso e como usar a biblioteca padrão do subprocesso Python.
Ao final deste tutorial, você irá:
- Entenda o conceito de subprocesso
- Aprenderam o básico da biblioteca de subprocessos Python
- Pratique suas habilidades em Python com exemplos úteis
Vamos entrar nisso
O conceito de subprocesso
Em termos gerais, um subprocesso é um processo de computador criado por outro processo.
Podemos pensar em um subprocesso como uma árvore, em que cada processo pai possui processos filho sendo executados por trás dele. Eu sei que isso pode ser bastante confuso, mas vamos ver com um gráfico simples.

Existem várias maneiras de visualizar o processo em execução em nosso computador. Por exemplo, em UNIX (Linux e MAC), temos htop, que é um visualizador de processo interativo.

O modo de árvore é a ferramenta mais útil para dar uma olhada nos subprocessos em execução. Podemos ativá-lo com F5 .
Se dermos uma olhada de perto na seção de comandos, podemos notar a estrutura dos processos em execução em nosso computador.

Tudo começa com / sbin / init que é o comando que inicia cada processo em nosso computador. A partir desse ponto, podemos ver o início de outros processos como xfce4-screenshoter e o xfce4-terminal (que conduz a ainda mais subprocessos)
Dando uma olhada no Windows, temos o gerenciador de tarefas mítico que resulta útil ao matar aqueles programas que travam em nossa máquina.

Agora temos um conceito claro como cristal. Vamos ver como podemos implementar subprocessos em Python.
Subprocessos em Python
Um subprocesso em Python é uma tarefa que um script python delega ao sistema operacional (SO).
A biblioteca de subprocessos nos permite executar e gerenciar subprocessos diretamente do Python. Isso envolve trabalhar com a entrada padrão stdin , saída padrão stdout e códigos de retorno.
Não precisamos instalá-lo com o PIP, pois faz parte da biblioteca padrão do Python.
Portanto, podemos começar a usar subprocessos em python apenas importando o módulo.
import subprocess # Using the module ....Observação: para acompanhar este artigo, você deve ter o Python 3.5 +
Para verificar a versão do Python que você tem atualmente, apenas execute.
❯ python --version Python 3.9.5 # My resultCaso a versão do Python que você obtenha seja 2.x, você pode usar o seguinte comando
python3 --versionContinuando com o tópico, a ideia principal por trás da biblioteca de subprocesso é ser capaz de interagir com o sistema operacional executando quaisquer comandos que quisermos, diretamente do interpretador Python.
Isso significa que podemos fazer o que quisermos, desde que nosso sistema operacional nos permita (e desde que você não remova seu sistema de arquivos raiz).
Vamos ver como usá-lo criando um script simples que lista os arquivos do diretório atual.
Primeiro aplicativo de subprocesso
Primeiro, vamos criar um arquivo list_dir.py . Este será o arquivo onde vamos experimentar os arquivos de listagem.
touch list_dir.pyAgora vamos abrir esse arquivo e usar o código a seguir.
import subprocess subprocess.run('ls')Primeiro, estamos importando o módulo de subprocesso e, em seguida, usando a função run que executa, o comando que passamos como um argumento.
Esta função foi introduzida no Python 3.5, como um atalho amigável para subprocess.Popen. A função subprocess.run nos permite executar um comando e esperar que ele termine, em contraste com Popen, onde temos a opção de chamar a comunicação mais tarde.
Falando sobre a saída do código, ls é um comando do UNIX que lista os arquivos do diretório em que você está. Portanto, se você executar este comando, obterá uma lista dos arquivos presentes no diretório atual.
❯ python list_dir.py example.py LICENSE list_dir.py README.mdNota: Leve em consideração que, se você estiver no Windows, precisará usar comandos diferentes. Por exemplo, em vez de usar “ls”, você pode usar “dir”
Isso pode parecer muito simples e você está certo. Você deseja ter uma abordagem completa de todo o poder que o shell traz para você. Portanto, vamos aprender como passar argumentos para o shell com o subprocesso.
Por exemplo, para listar também os arquivos ocultos (aqueles que começam com um ponto), e também listar todos os metadados dos arquivos, escrevemos o seguinte código.
import subprocess # subprocess.run('ls') # Simple command subprocess.run('ls -la', shell=True)Estamos executando este comando como uma string e usando o argumento shell . Isso significa que estamos invocando um shell no início da execução de nosso subprocesso e o argumento do comando é interpretado diretamente pelo shell.
No entanto, o uso do shell = True tem muitas desvantagens, e as piores são as possíveis falhas de segurança. Você pode ler sobre eles na documentação oficial.
A melhor maneira de passar comandos para a função run é usar uma lista onde lst [0] é o comando a ser chamado (ls neste caso) e lst [n] são os argumentos desse comando.
Se fizermos isso, nosso código ficará assim.
import subprocess # subprocess.run('ls') # Simple command # subprocess.run('ls -la', shell=True) # Dangerous command subprocess.run(['ls', '-la'])Se quisermos armazenar a saída padrão de um subprocesso em uma variável, podemos fazer isso definindo o argumento capture_output como true.
list_of_files = subprocess.run(['ls', '-la'], capture_output=True) print(list_of_files.stdout) ❯ python list_dir.py b'total 36\ndrwxr-xr-x 3 daniel daniel 4096 may 20 21:08 .\ndrwx------ 30 daniel daniel 4096 may 20 18:03 ..\n-rw-r--r-- 1 daniel daniel 55 may 20 20:18 example.py\ndrwxr-xr-x 8 daniel daniel 4096 may 20 17:31 .git\n-rw-r--r-- 1 daniel daniel 2160 may 17 22:23 .gitignore\n-rw-r--r-- 1 daniel daniel 271 may 20 19:53 internet_checker.py\n-rw-r--r-- 1 daniel daniel 1076 may 17 22:23 LICENSE\n-rw-r--r-- 1 daniel daniel 216 may 20 22:12 list_dir.py\n-rw-r--r-- 1 daniel daniel 22 may 17 22:23 README.md\n'Para acessar a saída de um processo, usamos o atributo de instância stdout .
Nesse caso, queremos armazenar a saída como uma string, em vez de bytes, e podemos fazer isso definindo o argumento de texto como verdadeiro.
list_of_files = subprocess.run(['ls', '-la'], capture_output=True, text=True) print(list_of_files.stdout) ❯ python list_dir.py total 36 drwxr-xr-x 3 daniel daniel 4096 may 20 21:08 . drwx------ 30 daniel daniel 4096 may 20 18:03 .. -rw-r--r-- 1 daniel daniel 55 may 20 20:18 example.py drwxr-xr-x 8 daniel daniel 4096 may 20 17:31 .git -rw-r--r-- 1 daniel daniel 2160 may 17 22:23 .gitignore -rw-r--r-- 1 daniel daniel 271 may 20 19:53 internet_checker.py -rw-r--r-- 1 daniel daniel 1076 may 17 22:23 LICENSE -rw-r--r-- 1 daniel daniel 227 may 20 22:14 list_dir.py -rw-r--r-- 1 daniel daniel 22 may 17 22:23 README.mdPerfeito, agora que sabemos o básico da biblioteca de subprocesso , é hora de passar para alguns exemplos de uso.
Exemplos de uso de subprocesso em Python
Nesta seção, revisaremos alguns usos práticos da biblioteca de subprocessos. Você pode verificar todos eles neste repositório Github.
Verificador de programa
Um dos principais usos desta biblioteca é a capacidade de fazer operações de sistema operacional simples.
Por exemplo, um script simples que verifica se um programa está instalado. No Linux, podemos fazer isso com o comando which .

'''Program checker with subprocess''' import subprocess program = 'git' process = subprocess. run(['which', program], capture_output=True, text=True) if process.returncode == 0: print(f'The program "{program}" is installed') print(f'The location of the binary is: {process.stdout}') else: print(f'Sorry the {program} is not installed') print(process.stderr)Nota: No UNIX, quando um comando é bem-sucedido, seu código de status é 0. Caso contrário, algo deu errado durante a execução
Como não estamos usando o argumento shell = True , podemos receber a entrada do usuário com segurança. Além disso, podemos verificar se a entrada é um programa válido com um padrão regex.
import subprocess import re programs = input('Separe the programs with a space: ').split() secure_pattern = '[\w\d]' for program in programs: if not re.match(secure_pattern, program): print("Sorry we can't check that program") continue process = subprocess. run( ['which', program], capture_output=True, text=True) if process.returncode == 0: print(f'The program "{program}" is installed') print(f'The location of the binary is: {process.stdout}') else: print(f'Sorry the {program} is not installed') print(process.stderr) print('\n')Nesse caso, estamos obtendo os programas do usuário e usando uma expressão regex que certifica que a string do programa inclui apenas letras e dígitos. Verificamos a existência de cada programa com um loop for a.
Grep simples em Python
Seu amigo Tom tem uma lista de padrões em um arquivo de texto e outro arquivo grande no qual deseja obter o número de correspondências para cada padrão. Ele passava horas executando o comando grep para cada padrão.
Felizmente, você sabe como resolver esse problema com Python e o ajudará a realizar essa tarefa em poucos segundos.
import subprocess patterns_file = 'patterns.txt' readfile = 'romeo-full.txt' with open(patterns_file, 'r') as f: for pattern in f: pattern = pattern.strip() process = subprocess.run( ['grep', '-c', f'{pattern}', readfile], capture_output=True, text=True) if int(process.stdout) == 0: print( f'The pattern "{pattern}" did not match any line of {readfile}') continue print(f'The pattern "{pattern}" matched {process.stdout.strip()} times')Dando uma olhada neste arquivo, definimos duas variáveis que são os nomes dos arquivos com os quais queremos trabalhar. Em seguida, abrimos o arquivo que contém todos os padrões e iteramos sobre eles. Em seguida, chamamos um subprocesso que executa um comando grep com o sinalizador “-c” (significa contagem) e determinamos a saída da correspondência com uma condicional.
Se você executar este arquivo (lembre-se de que você pode baixar os arquivos de texto do repositório Github)
Configure um virtualenv com subprocesso
Uma das coisas mais legais que você pode fazer com Python é a automação de processos. Esse tipo de script pode economizar horas de tempo por semana.
Por exemplo, vamos criar um script de configuração que cria um ambiente virtual para nós e tenta encontrar um arquivo requirements.txt no diretório atual para instalar todas as dependências.
import subprocess from pathlib import Path VENV_NAME = '.venv' REQUIREMENTS = 'requirements.txt' process1 = subprocess.run(['which', 'python3'], capture_output=True, text=True) if process1.returncode != 0: raise OSError('Sorry python3 is not installed') python_bin = process1.stdout.strip() print(f'Python found in: {python_bin}') process2 = subprocess.run('echo "$SHELL"', shell=True, capture_output=True, text=True) shell_bin = process2.stdout.split('/')[-1] create_venv = subprocess.run([python_bin, '-m', 'venv', VENV_NAME], check=True) if create_venv.returncode == 0: print(f'Your venv {VENV_NAME} has been created') pip_bin = f'{VENV_NAME}/bin/pip3' if Path(REQUIREMENTS).exists(): print(f'Requirements file "{REQUIREMENTS}" found') print('Installing requirements') subprocess.run([pip_bin, 'install', '-r', REQUIREMENTS]) print('Process completed! Now activate your environment with "source .venv/bin/activate"') else: print("No requirements specified ...")Nesse caso, estamos usando vários processos e analisando os dados de que precisamos em nosso script Python. Também estamos usando a biblioteca pathlib, que nos permite descobrir se o arquivo requirements.txt existe.
Se você executar o arquivo python, receberá algumas mensagens úteis sobre o que está acontecendo com o sistema operacional.
❯ python setup.py Python found in: /usr/bin/python3 Your venv .venv has been created Requirements file "requirements.txt" found Installing requirements Collecting asgiref==3.3.4 ....... Process completed! Now activate your environment with "source .venv/bin/activate"Observe que obtemos a saída do processo de instalação porque não estamos redirecionando a saída padrão para uma variável.
Execute outra linguagem de programação
Podemos executar outras linguagens de programação com python e obter a saída desses arquivos. Isso é possível porque os subprocessos interagem diretamente com o sistema operativo.
Por exemplo, vamos criar um programa hello world em C ++ e Java. Para executar o arquivo a seguir, você precisará instalar os compiladores C ++ e Java.
helloworld.cpp
#include <iostream> int main(){ std::cout << "This is a hello world in C++" << std::endl; return 0; }
helloworld.java
class HelloWorld{ public static void main(String args[]){ System.out.println("This is a hello world in Java"); } }
Eu sei que isso parece muito código em comparação com um simples Python one-liner, mas isso é apenas para fins de teste.
Vamos criar um script Python que executa todos os arquivos C ++ e Java em um diretório. Para fazer isso primeiro, queremos obter uma lista de arquivos dependendo da extensão do arquivo, e o glob nos permite fazer isso facilmente!
from glob import glob # Gets files with each extension java_files = glob('*.java') cpp_files = glob('*.cpp')Depois disso, podemos começar a usar subprocessos para executar cada tipo de arquivo.
for file in cpp_files: process = subprocess.run(f'g++ {file} -o out; ./out', shell=True, capture_output=True, text=True) output = process.stdout.strip() + ' BTW this was runned by Python' print(output) for file in java_files: without_ext = file.strip('.java') process = subprocess.run(f'java {file}; java {without_ext}',shell=True, capture_output=True, text=True) output = process.stdout.strip() + ' A Python subprocess runned this :)' print(output)Um pequeno truque é usar a faixa de função de string para modificar a saída e obter apenas o que precisamos.
Nota: Tenha cuidado ao executar arquivos Java ou C ++ grandes, pois estamos carregando sua saída na memória e isso pode causar um vazamento de memória.
Abra programas externos
Somos capazes de executar outros programas apenas chamando sua localização de binários por meio de um subprocesso.
Vamos experimentar abrindo o brave , meu navegador preferido.
import subprocess subprocess.run('brave')Isso abrirá uma instância do navegador ou apenas outra guia se você já estiver executando o navegador.

Como com qualquer outro programa que aceita sinalizadores, podemos usá-los para produzir o comportamento desejado.
import subprocess subprocess.run(['brave', '--incognito']) 
Resumindo
Um subprocesso é um processo de computador criado por outro processo. Podemos verificar os processos que nosso computador está executando com ferramentas como o htop e o gerenciador de tarefas.
Python tem sua própria biblioteca para trabalhar com subprocessos. Atualmente, a função run fornece uma interface simples para criar e gerenciar subprocessos.
Podemos criar qualquer tipo de aplicativo com eles porque estamos interagindo diretamente com o SO.
Por fim, lembre-se de que a melhor maneira de aprender é criando algo que você gostaria de usar.
