Aller au contenu
Cheat Sheet
Python

[Python] Exécuter un programme externe et interagir avec lui

  • 18 mars 202218 mars 2022

Pour interagir avec un programme en ligne de commande exécuté depuis un script Python, ce n’est pas aussi simple que ça n’y paraît…

Supposons que nous ayons un programme externe qui s’appelle question.py :

import random

if __name__ == '__main__':
    print("Faisons quelques multiplications...")
    score = 0
    for i in range(3):
        a = random.randrange(2, 20)
        b = random.randrange(2, 20)
        res = int(input(f"{a} x {b} = "))
        if res == a * b:
            print("Bravo !")
            score += 1
        else:
            print(f"Dommage, la réponse était {a * b}.")
    print(f"Vous avez {score} bonne(s) réponse(s) sur 3.")

Ce programme va poser plusieurs multiplications à la suite et comptera combien de bonnes réponses ont été données. Simple.

L’objectif est de créer un programme Python qui va :

  • Exécuter question.py
  • Lire les questions.
  • Calculer pour chaque question la bonne réponse.
  • Envoyer la réponse au programme.

jusqu’à ce que le programme se termine.

On pourrait se dire qu’il suffit d’exécuter le programme avec un Popen et de lire les lignes une à une.
Problème : comme le programme externe est en attente d’une réponse, la fonction readline()reste bloquée.

Pour résoudre le problème, on peut utiliser la librairie asyncio qui permet de manipuler des Stream de manière asynchrone. Ainsi on pourra lire tout en appliquant un timeout.

Exemple de solution :

# -*- coding: utf-8 -*-
import asyncio
import sys
from asyncio.subprocess import PIPE, STDOUT
import re 

async def read_line(process, timeout=None):
    """
    Read line from process until timeout.
    """
    line = b''
    while True:
        try:
            char = await asyncio.wait_for(process.stdout.read(1), timeout)
            if not char:
                return line.decode('utf-8')
            line += char
            
        except asyncio.TimeoutError:
            return line.decode('utf-8')


async def run_command(*args, timeout=None):
    process = await asyncio.create_subprocess_exec(*args, stdout=PIPE, stdin=PIPE, stderr=STDOUT)

    while True:
        txt = await read_line(process, timeout)
        if not txt:
            break
        print(txt)
        res = re.search("(\d+) x (\d+)", txt.split("\n")[-1])
        if res:
            a, b = res.groups()
            c = str(int(a) * int(b))
            print(f'>> On va répondre {c}')
            
            process.stdin.write(c.encode())
            process.stdin.write(b'\n')
    return await process.wait()


if __name__ == '__main__':
    if sys.platform == "win32":
        loop = asyncio.ProactorEventLoop()
        asyncio.set_event_loop(loop)
    else:
        loop = asyncio.get_event_loop()

    returncode = loop.run_until_complete(run_command('python', 'question.py', timeout=1))
    loop.close()
[Synology] Exécuter un script au démarrage
[Python] Benedict : une autre façon de jouer avec les dict

Articles similaires

[Python] Benedict : une autre…
Un package Python nécessite Visual…
Publier un site Flask sur…
[Python] Combien de temps met…
[Python / Selenium] Regarder les…
[Python] Petites fonctions qui vont…
[Notepad++] Enchaîner les “rechercher /…
[Python] Transformer un tableau de…
[Selenium] utiliser une instance de…
Créer un VirtualEnv pour Python

Catégories

  • Android
  • Calibre
  • Excel
  • Git
  • Google Sheet
  • Knime
  • Linux
  • Logiciels
  • Matériel
  • Non classé
  • Notepad++
  • Power BI
  • Programmation
  • Python
  • Qlik
  • Synology
  • Visual Studio Code
  • Windows
  • Word
  • WordPress

Étiquettes

android apache apn artefact connexion contrast convert encode escalier excel ffmpeg filter firefox generators hash kobo lambda linux map markdown max md5 min mp3 notepad++ office partage php pip potplayer python qlik qliksense qlikview selenium sha1 styles synology venv virtualenv visual basic wav windows word wordpress

Tags

android apache apn artefact connexion contrast convert encode escalier excel ffmpeg filter firefox generators hash kobo lambda linux map markdown max md5 min mp3 notepad++ office partage php pip potplayer python qlik qliksense qlikview selenium sha1 styles synology venv virtualenv visual basic wav windows word wordpress
Thème par Colorlib Propulsé par WordPress