Aller au contenu

Interagir avec le système et la ligne de commande

os : environnement du processus

Élément Usage
getenv(name, default) Lire une variable d'environnement.
environ Consulter ou modifier l'environnement du processus.
getcwd() / chdir(path) Lire / changer le répertoire de travail.
walk(path) Parcourir une arborescence.
cpu_count() Nombre de processeurs logiques détectés, ou None.
import os

mode = os.getenv("APP_ENVIRONMENT", "development")
print(mode)

Pour les chemins et les fichiers, pathlib offre souvent une API plus expressive. os reste utile pour l'environnement et les fonctionnalités du système ; certaines varient selon la plateforme.

Parallèle C# et .NET

string mode = Environment.GetEnvironmentVariable("APP_ENVIRONMENT") ?? "development";
Console.WriteLine(mode);
Console.WriteLine(Environment.CurrentDirectory);
Console.WriteLine(Environment.ProcessorCount);

Environment couvre les variables et plusieurs informations système. Directory.EnumerateFiles() et EnumerateDirectories() permettent le parcours des dossiers. ProcessorCount et os.cpu_count() n’ont pas nécessairement les mêmes règles en présence de quotas ou d’affinités. Modifier une variable d’environnement du processus ne modifie pas celle du processus parent.

sys : interpréteur et arguments

Élément Usage
argv Arguments de ligne de commande.
executable Chemin de l'interpréteur.
version_info Version structurée de Python.
path Chemins de recherche des modules.
stdin, stdout, stderr Flux standard.
exit(code) Lever SystemExit pour demander la sortie.
import sys

print(sys.executable)
print(sys.version_info.major)
print("Message de diagnostic", file=sys.stderr)

sys.argv[0] désigne habituellement le script ou le point d'entrée. Pour interpréter plusieurs options, utilisons argparse.

Parallèle C# et .NET

Console.WriteLine(Environment.ProcessPath);
Console.WriteLine(Environment.Version);
Console.Error.WriteLine("Message de diagnostic");
string[] commandLine = Environment.GetCommandLineArgs();

Environment.Version donne la version du runtime .NET, pas celle du langage C#. Le point d’entrée console expose aussi args, sans inclure le programme comme GetCommandLineArgs(). Il n’existe pas de sys.path identique : le chargement des assemblies suit d’autres règles. Environment.Exit() termine le processus ; ce n’est pas la levée interceptable d’une exception comme sys.exit().

argparse : arguments nommés et aide automatique

ArgumentParser décrit les paramètres d'un programme. add_argument() les déclare et parse_args() les interprète.

Enregistrons cet exemple dans greet.py :

import argparse

parser = argparse.ArgumentParser(description="Afficher un message.")
parser.add_argument("name", help="Nom de la personne")
parser.add_argument("--count", type=int, default=1, help="Nombre de répétitions")
args = parser.parse_args()

for _ in range(args.count):
    print(f"Bonjour {args.name} !")

Exécution :

python greet.py James --count 2
python greet.py --help

Le module produit l'aide et signale les arguments invalides. Dans un exemple sans ligne de commande, parse_args(["James", "--count", "2"]) permet de fournir explicitement les arguments.

Parallèle C# et .NET

// Démonstration limitée : arguments fournis explicitement.
string[] arguments = { "James", "--count", "2" };
if (arguments.Length == 3 && arguments[1] == "--count"
    && int.TryParse(arguments[2], out int count) && count >= 0)
{
    for (int i = 0; i < count; i++)
        Console.WriteLine($"Bonjour {arguments[0]} !");
}
else Console.Error.WriteLine("Usage : greet <name> --count <entier positif ou nul>");

La bibliothèque de base fournit les arguments, sans reproduire tout argparse. Ce parseur volontairement limité n’a ni valeur par défaut ni aide générée. Pour ces fonctionnalités, System.CommandLine est une bibliothèque Microsoft distribuée par NuGet ; sa présence n’est pas implicite dans une application console.

subprocess : lancer un programme externe

run() exécute une commande et attend sa fin. Popen convient au contrôle plus fin d'un processus.

import subprocess
import sys

result = subprocess.run(
    [sys.executable, "-c", "print('Bonjour depuis un autre processus')"],
    capture_output=True,
    text=True,
    encoding="utf-8",
    check=True,
    timeout=10,
)
print(result.stdout.strip())

check=True provoque CalledProcessError en cas de code de retour non nul. timeout borne l'attente. Passons les arguments dans une liste avec le comportement par défaut shell=False, en particulier lorsque certaines valeurs viennent de l'extérieur.

Parallèle C# et .NET

var start = new ProcessStartInfo("dotnet")
{
    UseShellExecute = false,
    RedirectStandardOutput = true,
    RedirectStandardError = true
};
start.ArgumentList.Add("--version");
using Process process = Process.Start(start)!;
Task<string> stdout = process.StandardOutput.ReadToEndAsync();
Task<string> stderr = process.StandardError.ReadToEndAsync();
using var timeout = new CancellationTokenSource(TimeSpan.FromSeconds(10));
try { await process.WaitForExitAsync(timeout.Token); }
catch (OperationCanceledException)
{
    process.Kill(entireProcessTree: true);
    await process.WaitForExitAsync();
    throw;
}
await Task.WhenAll(stdout, stderr);
if (process.ExitCode != 0) throw new InvalidOperationException(await stderr);
Console.WriteLine((await stdout).Trim());

Cet exemple exige le SDK dotnet dans le chemin des exécutables. Process ne possède pas de check=True : le code de sortie est vérifié explicitement. Les deux sorties sont lues en parallèle pour éviter un blocage sur un tampon plein. Annuler WaitForExitAsync() ne termine pas le processus ; la branche d’annulation le fait ici explicitement.

logging : journaliser les événements

Élément Usage
basicConfig() Configuration initiale simple.
getLogger(name) Obtenir un journal nommé.
debug(), info() Diagnostic détaillé / suivi normal.
warning(), error(), critical() Anomalies de gravité croissante.
exception() Journaliser une erreur avec sa trace dans un bloc d'exception.
import logging

logging.basicConfig(level=logging.INFO, format="%(levelname)s: %(message)s")
logger = logging.getLogger(__name__)
logger.info("Traitement de %s produits", 12)

Configurons les journaux au point d'entrée de l'application. basicConfig() peut rester sans effet si des gestionnaires existent déjà. Dans un module réutilisable, obtenons un journal sans imposer la configuration globale.

Parallèle C# et .NET

Trace.Listeners.Add(new TextWriterTraceListener(Console.Out));
Trace.AutoFlush = true;
Trace.TraceInformation("Traitement de {0} produits", 12);

System.Diagnostics.Trace fournit un mécanisme de diagnostic intégré, dont les appels dépendent notamment du symbole TRACE. Pour une API de journalisation structurée proche des usages applicatifs, Microsoft.Extensions.Logging fournit ILogger<T> et des fournisseurs configurables. Dans une console minimale, ces composants doivent être ajoutés/configurés ; ils sont couramment intégrés aux modèles ASP.NET Core. Console.WriteLine() seul n’est pas un système de journalisation équivalent.