Depuis des années, j’explore les mécanismes internes de *Python* pour bâtir des outils robustes et sécurisés. Dans cet article, je décortique eval et exec, deux fonctions puissantes d’exécution dynamique qui permettent d’interpréter du code à la volée. Je raconte des cas réels où j’ai dû choisir entre flexibilité et sécurité, je donne des exemples concrets, des astuces pour la validation d’entrée, et des alternatives plus sûres pour éviter les risques de sécurité liés au traitement de code arbitraire. Mon objectif : vous rendre autonome et prudent, sans sacrifier l’efficacité.
- Eval : pour évaluer une expression et récupérer un résultat.
- Exec : pour exécuter des blocs de code et générer des effets de bord.
- Attention aux risques de sécurité dès que l’entrée n’est pas maîtrisée.
- Pratiques recommandées : validation d’entrée, sandboxing, et alternatives comme ast.literal_eval.
- Exemples pratiques et cas d’usage réels pour la programmation quotidienne.
Réponse rapide : eval évalue une seule expression et renvoie sa valeur, tandis que exec exécute n’importe quel bloc de code mais retourne None. Pour des entrées non fiables, privilégiez la validation d’entrée, ast.literal_eval ou exécutez dans des namespaces restreints afin de réduire les risques de sécurité liés à l’exécution de code arbitraire.
Différence essentielle entre eval() et exec() en Python
Dans ma pratique, la confusion entre eval et exec est fréquente. Je commence toujours par clarifier leur rôle. eval attend une chaîne qui représente une expression (comme « 2 + 2 » ou « len(liste) »), et renvoie sa valeur. exec accepte des instructions complètes : boucles, définitions de fonctions, assignations.
Exemple simple que j’ai utilisé en formation : eval(‘3 * x’) renvoie une valeur, exec(‘x = 5’) modifie l’environnement. Cette distinction guide le choix selon le besoin : récupérer un résultat ou produire des effets.

Insight : choisir eval pour une expression, exec pour un bloc.
Structure du code et valeurs retournées
J’explique souvent que eval est limité aux expressions ; lui passer une affectation provoque une SyntaxError. À l’inverse, exec exécute et renvoie None, car son but est les effets secondaires.
Si vous pesez performance et réutilisation, utilisez compile() pour transformer une chaîne en objet code, puis ré-exécutez cet objet plusieurs fois : ça réduit le surcoût d’analyse.
Insight : retour attendu = valeur pour eval, effets pour exec.
Cas d’usage pratiques et exemples concrets
J’ai utilisé exec pour charger dynamiquement des scripts de configuration dans un outil interne, et eval pour permettre des mini-formules utilisateur. Dans un cas client, remplacer eval par ast.literal_eval a empêché une fuite de données lors d’un test d’injection.
Exemples reproduisibles :
- Évaluer une expression mathématique : result = eval(’42 * a’)
- Exécuter un bloc : exec(‘for i in range(3): print(i)’)
- Compiler pour réutiliser : code = compile(‘x+1’, ‘<string>’, ‘eval’)
Pour maîtriser les contrôles de flux, je renvoie souvent vers des ressources sur les boucles for/while en Python et sur la gestion des fonctions avec args et kwargs en Python, car on combine fréquemment ces concepts avec l’exécution dynamique.

Insight : chaque usage doit être validé et limité.
Quand préférer compile() et objets code
Pour du code réutilisé intensivement, je recommande la compilation : compile(source, filename, mode) renvoie un objet code que l’on passe à eval ou exec. J’ai gagné en lisibilité et vitesse en compilant des expressions récurrentes dans un moteur de règles.
Note pratique : compiler en mode ‘eval’ produit une expression réutilisable ; ‘exec’ pour des blocs. Attention aux modes incompatibles : compiler une boucle en ‘eval’ échoue.
Insight : compile réduit le coût d’analyse et clarifie l’intention.
Risques de sécurité et bonnes pratiques
J’insiste toujours : l’exécution dynamique introduit des risques de sécurité majeurs dès que l’on traite de l’input utilisateur. Un code malveillant peut lire des fichiers, lancer des connexions réseau, ou détruire des données.
Voici les règles que j’applique systématiquement :
- Ne jamais exécuter directement du texte non validé.
- Utiliser ast.literal_eval pour les littéraux simples (listes, dicts, nombres).
- Limiter les namespaces passés à eval/exec : exec(code, {‘__builtins__’: None}, safe_locals).
- Valider et normaliser l’entrée (whitelisting des tokens autorisés).
- Isoler l’exécution dans un processus ou un conteneur si nécessaire.
Pour approfondir l’analyse de code et détecter des patterns dangereux, je combine ces pratiques avec des tests unitaires et des scans statiques. J’ai intégré ces contrôles dans des outils de revue de code et dans des pipelines CI pour sécuriser la chaîne de livraison.
Insight : la sécurité commence par la validation et l’isolation.

Alternatives et complémentarités
Souvent, la vraie solution n’est pas d’exécuter du code dynamique. Pour des besoins courants, j’ai préféré :
- Interpréter une mini-DSL contrôlée et parser les expressions au lieu d’utiliser eval.
- Utiliser des modules existants pour des tâches spécifiques : OCR (voir OCR avec Python et Tesseract), génération de PDF (PDF avec ReportLab), ou analyse de données en Python.
- Stocker des règles sous forme de données (JSON) et les appliquer via du code serveur validé.
Dans un projet de simulation, j’ai remplacé eval par un moteur de règles et réduit les incidents de production à zéro.
Insight : préférer des formats structurés et des moteurs dédiés.
Checklist pratique avant d’utiliser eval ou exec
Voici la liste que j’impose dans mes revues de code :
- Pourquoi : l’usage est-il indispensable ?
- Qui fournit l’entrée : interne ou externe ?
- Comment la valider : whitelist, regex, parsing ?
- Où exécuter : namespace limité, sandbox, processus séparé ?
- Audit : logs, monitoring, tests d’injection.
Pour mieux manipuler les structures de données avant d’envisager eval, maîtrisez les types fondamentaux et les structures comme les dictionnaires en Python ou les opérateurs arithmétiques (opérateurs arithmétiques).
Insight : une checklist évite les oublis critiques.
Quelques cas réels et anecdotes
Je me souviens d’un script interne qui utilisait eval pour calculer des formules métiers. Un utilisateur a inséré une expression provoquant une boucle infinie, bloquant le service. Après incident, nous avons transformé le système : parsing sécurisé + limites de temps d’exécution. Le résultat : meilleur suivi et moins d’incidents.
Ces retours d’expérience m’ont appris que la prudence paie toujours.
Insight : les erreurs d’exécution dynamique coûtent cher en production.
Ressources complémentaires et approfondissement
Si vous souhaitez creuser les sujets liés à la programmation et aux patterns d’architecture, consultez des guides pratiques comme modèles de machine learning en Python ou des tutoriels sur la manipulation de fichiers et réseaux comme client-serveur et sockets. Pour des projets modulaires, la lecture sur modules et packages m’a souvent aidé à éviter l’exécution dynamique quand une simple réorganisation du code suffisait.
Insight : la connaissance des bibliothèques réduit la tentation d’exécuter du code arbitraire.
Quelles sont les différences clés entre eval() et exec() ?
Eval évalue une expression et renvoie sa valeur. Exec exécute un bloc de code (fonctions, boucles, assignations) et retourne None. Choisissez eval pour un résultat, exec pour des effets de bord.
Comment limiter les risques de sécurité lorsque j’utilise eval ou exec ?
Validez l’entrée (whitelist), utilisez ast.literal_eval pour les littéraux, limitez les namespaces passés à eval/exec, ou exécutez dans un processus isolé. Le logging et les tests d’injection sont indispensables.
Quand faut-il préférer compile() ?
Compile est utile lorsque vous exécutez plusieurs fois le même code : il transforme une source en objet code réutilisable, réduisant le coût d’analyse. Choisissez le mode ‘eval’ pour une expression, ‘exec’ pour un bloc.
Existe-t-il des alternatives sûres à eval pour parser des expressions ?
Oui. ast.literal_eval permet d’évaluer seulement les littéraux Python. Pour des besoins avancés, implémentez une mini-DSL ou utilisez des bibliothèques spécialisées qui parsèment et valident les expressions.

