Geekflare cuenta con el apoyo de nuestra audiencia. Podemos ganar comisiones de afiliados comprando enlaces en este sitio.
Comparte en:

¿Qué es un subproceso en Python? [5 ejemplos de uso]

Subproceso
Escáner de seguridad de aplicaciones web Invicti – la única solución que ofrece verificación automática de vulnerabilidades con Proof-Based Scanning™.

Los subprocesos le permiten interactuar en un nivel totalmente nuevo con el sistema operativo.

Nuestra computadora ejecuta subprocesos todo el tiempo. De hecho, con solo leer este artículo, está ejecutando muchos procesos, como un administrador de red o el propio navegador de Internet.

Lo bueno de esto es que cualquier acción que hacemos en nuestra computadora implica invocar un subproceso. Eso sigue siendo cierto incluso si estamos escribiendo un sencillo "Hola Mundo" guión en pitón.

El concepto de subproceso puede parecer oscuro incluso si ha estado aprendiendo programación durante un tiempo. Este artículo analizará en profundidad el concepto principal del subproceso y cómo usar Python biblioteca estándar de subprocesos.

Al final de este tutorial, podrás:

  • Comprender el concepto de subproceso
  • Haber aprendido los conceptos básicos de la biblioteca de subprocesos de Python.
  • Practicó sus habilidades de Python con ejemplos útiles

Vamos a entrar en eso

El concepto de subproceso

En términos generales, un subproceso es un proceso informático creado por otro proceso.

Podemos pensar en un subproceso como un árbol, en el que cada proceso padre tiene procesos secundarios ejecutándose detrás de él. Sé que esto puede ser bastante confuso, pero veámoslo con un gráfico simple.

Hay varias formas en que podemos visualizar el proceso que se ejecuta en nuestra computadora. Por ejemplo, en UNIX (Linux y MAC) tenemos arriba, que es un visor de procesos interactivo.

Visor de procesos Htop

La modo árbol es la herramienta más útil para echar un vistazo a los subprocesos en ejecución. Podemos activarlo con F5.

Si echamos un vistazo de cerca a la sección de comandos, podemos notar la estructura de los procesos que se ejecutan en nuestra computadora.

Estructura del proceso Htop
Todo comienza con / sbin / init que es el comando que inicia cada proceso en nuestra computadora. A partir de ese punto, podemos ver el inicio de otros procesos como xfce4-capturador de pantalla y del xfce4-terminal (Lo que conduce a más subprocesos)

Echando un vistazo a Windows, tenemos el mítico administrador de tareas lo que resulta útil cuando se eliminan los programas que fallan en nuestra máquina.

Administrador de tareas de Windows

Ahora tenemos un concepto muy claro. Veamos cómo podemos implementar subprocesos en Python.

Subprocesos en Python

Un subproceso en Python es una tarea que un script de Python delega al sistema operativo (SO).

La biblioteca de subprocesos nos permite ejecutar y administrar subprocesos directamente desde Python. Eso implica trabajar con la entrada estándar stdin, salida estándar stdouty códigos de retorno.

No tenemos que instalarlo con PIP, ya que es parte de Python biblioteca estándar.

Por lo tanto, podemos comenzar a usar subprocesos en Python simplemente importando el módulo.

import subprocess

# Using the module ....

Nota: Para seguir este artículo, debe tener Python 3.5 +

A verifique la versión de python tiene actualmente, simplemente ejecute.

❯ python --version
Python 3.9.5 # My result

En caso de que la versión de Python que obtenga sea 2.x, puede usar el siguiente comando

python3 --version

Continuando con el tema, la idea principal detrás de la biblioteca de subprocesos es poder interactuar con el SO ejecutando los comandos que queramos, directamente desde el intérprete de Python.

Eso significa que podemos hacer lo que queramos, siempre que nuestro sistema operativo nos lo permita (y siempre que no elimines tu sistema de archivos raíz 😅).

Veamos cómo usarlo creando un script simple que enumere los archivos del directorio actual.

Primera aplicación de subproceso

Primero, creemos un archivo list_dir.py. Este será el archivo donde vamos a experimentar la lista de archivos.

touch list_dir.py

Ahora abramos ese archivo y usemos el siguiente código.

import subprocess 

subprocess.run('ls')

Primero, estamos importando el módulo de subproceso y luego usamos la función corrida que se ejecuta, el comando que pasamos como argumento.

Esta función se introdujo en Python 3.5, como un atajo amigable para subproceso.Popen. La función subprocess.run nos permite ejecutar un comando y esperar a que termine, a diferencia de Popen donde tenemos la opción de llamar a comunicarse más tarde.

Hablando de la salida del código, ls es un Comando UNIX que enumera los archivos del directorio en el que se encuentra. Por lo tanto, si ejecuta este comando, obtendrá una lista de los archivos presentes en el directorio actual.

❯ python list_dir.py
example.py  LICENSE  list_dir.py  README.md

Nota: Tenga en cuenta que si está en Windows, deberá usar diferentes comandos. Por ejemplo en lugar de usar "Ls"  puedes usar "Dir"

Esto puede parecer demasiado simple y tiene razón. Quieres tener un enfoque completo de todo el poder que te brinda el caparazón. Entonces, aprendamos cómo pasar argumentos al shell con subproceso.

Por ejemplo para listar también los archivos ocultos (aquellos que comienzan con un punto), y también listar todos los metadatos de los archivos, escribimos el siguiente código.

import subprocess

# subprocess.run('ls')  # Simple command

subprocess.run('ls -la', shell=True)

Ejecutamos este comando como una cadena y usamos el argumento shell. Eso significa que estamos invocando un shell al comienzo de la ejecución de nuestro subproceso, y el argumento del comando es interpretado directamente por el shell.

Sin embargo, el uso shell = Verdadero tiene muchas desventajas, y las peores son las posibles filtraciones de seguridad. Puedes leer sobre ellos en el documentación oficial.

La mejor manera de pasar comandos a la función de ejecución es usar una lista donde lst [0] es el comando para llamar (ls en este caso) y lst [n] son los argumentos de ese comando.

Si lo hacemos, nuestro código se verá así.

import subprocess

# subprocess.run('ls')  # Simple command

# subprocess.run('ls -la', shell=True) # Dangerous command

subprocess.run(['ls', '-la'])

Si queremos almacenar la salida estándar de un subproceso en una variable, podemos hacerlo estableciendo el argumento capture_output en verdadero.

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 acceder a la salida de un proceso, usamos el atributo de instancia stdout.

En este caso, queremos almacenar la salida como una cadena, en lugar de bytes, y podemos hacerlo configurando el argumento de texto como verdadero.

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.md

Perfecto, ahora que conocemos los conceptos básicos del subproceso biblioteca, es hora de pasar a algunos ejemplos de uso.

Ejemplos de uso de subprocesos en Python

En esta sección, revisaremos algunos usos prácticos de la biblioteca de subprocesos. Puedes consultarlos todos en este Repositorio de Github.

Program checker

Uno de los principales usos de esta biblioteca es la capacidad de realizar operaciones sencillas del sistema operativo.

Por ejemplo, un script simple que comprueba si un programa está instalado. En Linux, podemos hacer esto con el que mando.

'''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: En UNIX, cuando un comando tiene éxito, su código de estado es 0. De lo contrario, algo salió mal durante la ejecución.

Dado que no estamos usando el shell = Verdadero argumento, podemos tomar la entrada del usuario de forma segura. Además, podemos verificar si la entrada es un programa válido con un patrón de expresiones regulares.

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')

En este caso, obtenemos los programas del usuario y usamos una expresión regular que certifica que la cadena del programa solo incluye letras y dígitos. Comprobamos la existencia de cada programa con un bucle for a.

Nota: Marque esto probador de expresiones regulares en línea.

Simple Grep in Python

Tu amigo tom tiene una lista de patrones en un archivo de texto y otro archivo grande en el que quiere obtener el número de coincidencias para cada patrón. Pasaría horas ejecutando el comando grep para cada patrón.

Afortunadamente, sabes cómo resolver este problema con Python y lo ayudarás a realizar esta tarea en pocos 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')

Echando un vistazo a este archivo, definimos dos variables que son los nombres de archivo con los que queremos trabajar. Luego abrimos el archivo que contiene todos los patrones y los iteramos. A continuación, llamamos a un subproceso que ejecuta un comando grep con el "-C" flag (cuenta de medios) y determina la salida de la coincidencia con un condicional.

Si ejecuta este archivo (recuerde que puede descargar los archivos de texto del Repo de Github)

Set up a virtualenv with subprocess

Una de las mejores cosas que puede hacer con Python es la automatización de procesos. Este tipo de secuencia de comandos puede ahorrarle horas de tiempo a la semana.

Por ejemplo, vamos a crear un script de configuración que crea un entorno virtual para nosotros e intenta encontrar un requerimientos.txt archivo en el directorio actual para instalar todas las dependencias.

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 ...")

En este caso, estamos usando varios procesos y analizando los datos que necesitamos en nuestro script de Python. También estamos usando el Pathlib biblioteca que nos permite calcularlo si el requerimientos.txt El archivo existe.

Si ejecuta el archivo python, obtendrá algunos mensajes útiles sobre lo que está sucediendo con el sistema operativo.

❯ 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"

Tenga en cuenta que obtenemos el resultado del proceso de instalación porque no estamos redirigiendo el resultado estándar a una variable.

Run another Programming Language

Podemos ejecutar otros lenguajes de programación con python y obtener el resultado de esos archivos. Esto es posible porque los subprocesos interactúan directamente con el sistema operativo.

Por ejemplo, creemos un programa de hola mundo en C ++ y Java. Para ejecutar el siguiente archivo, deberá instalar C + + y Java compiladores.

holamundo.cpp

#include <iostream>

int main(){
    std::cout << "This is a hello world in C++" << std::endl;
    return 0;
}


holamundo.java

class HelloWorld{  
    public static void main(String args[]){  
     System.out.println("This is a hello world in Java");  
    }  
}  


Sé que esto parece mucho código en comparación con una simple línea de Python, pero esto es solo para fines de prueba.

Vamos a crear un script de Python que ejecute todos los archivos C ++ y Java en un directorio. Para hacer esto primero queremos obtener una lista de archivos dependiendo de la extensión del archivo, y glob ¡nos permite hacerlo fácilmente!

from glob import glob

# Gets files with each extension
java_files = glob('*.java')

cpp_files = glob('*.cpp')

Después de eso, podemos comenzar a usar subprocesos para ejecutar cada tipo de archivo.

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)

Un pequeño truco es usar la función de cadena tira para modificar la salida y obtener solo lo que necesitamos.

Nota: Tenga cuidado al ejecutar archivos grandes de Java o C ++, ya que estamos cargando su salida en la memoria y eso podría producir una pérdida de memoria.

Open external programs

Podemos ejecutar otros programas simplemente llamando a la ubicación de sus binarios a través de un subproceso.

Probémoslo abriendo valiente, mi navegador web preferido.

import subprocess

subprocess.run('brave')

Esto abrirá una instancia del navegador, o simplemente otra pestaña si ya lo ha ejecutado.

Navegador abierto

Como con cualquier otro programa que acepta banderas, podemos usarlas para producir el comportamiento deseado.

import subprocess

subprocess.run(['brave', '--incognito'])
Bandera de incógnito

En resumen

Un subproceso es un proceso informático creado por otro proceso. Podemos verificar los procesos que nuestra computadora está ejecutando con herramientas como htop y el administrador de tareas.

Python tiene su propia biblioteca para trabajar con subprocesos. Actualmente, el corrida La función nos brinda una interfaz simple para crear y administrar subprocesos.

Podemos crear cualquier tipo de aplicación con ellos porque estamos interactuando directamente con el SO.

Finalmente, recuerde que la mejor manera de aprender es crea algo te gustaría usar

Gracias a nuestros patrocinadores
Más lecturas interesantes sobre el desarrollo
Impulse su negocio
Algunas de las herramientas y servicios para ayudar a que su negocio crezca.
  • Invicti utiliza Proof-Based Scanning™ para verificar automáticamente las vulnerabilidades identificadas y generar resultados procesables en cuestión de horas.
    Prueba Invicti
  • Web scraping, proxy residencial, administrador de proxy, desbloqueador web, rastreador de motores de búsqueda y todo lo que necesita para recopilar datos web.
    Prueba Brightdata
  • Semrush es una solución de marketing digital todo en uno con más de 50 herramientas en SEO, redes sociales y marketing de contenido.
    Prueba Semrush
  • Intruder es un escáner de vulnerabilidades en línea que encuentra debilidades de ciberseguridad en su infraestructura, para evitar costosas filtraciones de datos.
    Intente Intruder