Python >> Tutoriel Python >  >> Python Tag >> exec()

Python exec() — Guide du hacker pour une fonction dangereuse

exec() de Python La fonction exécute le code Python que vous transmettez en tant qu'argument de chaîne ou d'objet exécutable. C'est ce qu'on appelle l'exécution dynamique car, contrairement à la norme statique Code Python, vous pouvez générer du code et l'exécuter lors de l'exécution. De cette façon, vous pouvez exécuter du code Python créé par programme.

Vous êtes-vous déjà interrogé sur les limites d'une seule ligne de code Python ? Eh bien, il n'y a pas de limites à cela, si vous connaissez cette fonction puissante. Ce tutoriel vous montre comment utiliser le exec() intégré de Python fonction.

Exemples d'utilisation

Apprenez par l'exemple ! Voici quelques exemples d'utilisation du exec() fonction intégrée :

>>> program = 'print("hello world")'
>>> exec(program)
hello world

Tout d'abord, vous créez un programme qui n'est qu'une chaîne contenant du code Python. Deuxièmement, vous exécutez exec(program) pour exécuter le programme en Python.

>>> exec('x=2; y=4; print(x+y)')
6

L'extrait de code précédent, vous avez vu comment exécuter plusieurs "lignes de code" dans une seule ligne de code. Vous créez deux variables x et y et imprimez la somme des deux. Vous compressez toutes ces lignes en une seule en utilisant le point-virgule ;

Voici comment vous pouvez utiliser le exec() déclaration dans le exec() en donnant à l'utilisateur le pouvoir d'exécuter du code dans votre environnement. Soyez prudent avec ça! Cela ouvre toutes sortes de problèmes de sécurité car n'importe quel utilisateur peut exécuter pratiquement n'importe quel programme sur votre ordinateur - un cauchemar pour des considérations de sécurité !

>>> exec('x = input("Your code: "); exec(x)')
Your code: print('hi')
hi

Alors, à quoi ressemble formellement la syntaxe ?

Syntaxe Exec()

Vous pouvez utiliser le exec() méthode avec trois listes d'arguments différentes.

Syntax: 
exec(object)
exec(object, globals)
exec(object, globals, locals) 
Arguments object Une chaîne ou un objet code à exécuter.
globals Facultatif. Un dictionnaire dans lequel vous pouvez définir des variables qui doivent être globalement accessibles par le object exécuté (espace de noms local).
locals Facultatif. Un dictionnaire dans lequel vous pouvez définir des variables qui doivent être accessibles localement par le object exécuté (espace de noms global).
Valeur de retour None Ne renvoie rien mais cela peut quand même avoir des effets secondaires importants !

Valeur de retour Python exec()

La valeur de retour de exec() est None . Cependant, il peut avoir exécuté toutes sortes de fonctions avec toutes sortes d'effets secondaires tels que la modification de la structure des dossiers sur votre système d'exploitation, la création de nouveaux fichiers, le déploiement d'un cheval de Troie ou le détournement de vos Bitcoins.


Mais avant de continuer, je suis ravi de vous présenter mon nouveau livre Python Python One-Liners (Lien Amazon).

Si vous aimez les one-liners, vous allez adorer le livre. Il vous apprendra tout ce qu'il y a à savoir sur une seule ligne de code Python. Mais c'est aussi une introduction à l'informatique , science des données, apprentissage automatique et algorithmes. L'univers en une seule ligne de Python !

Le livre est sorti en 2020 avec l'éditeur de livres de programmation de classe mondiale NoStarch Press (San Francisco).

Lien :https://nostarch.com/pythononeliners

[Zone de danger] Entrée utilisateur Python exec()

Vous pouvez utiliser le exec() fonction pour exécuter du code saisi dynamiquement par l'utilisateur :

program = input('your code: ')
exec(program)

Ceci est très dangereux car l'utilisateur peut en fait exécuter n'importe quel code dans votre environnement. Si vous l'exécutez sur votre serveur, l'utilisateur peut tenter de supprimer tous les fichiers de votre serveur ! Par exemple, l'utilisateur peut utiliser la commande os.system('rm -rf *') pour supprimer tous les fichiers et dossiers.

L'exécution de ces deux lignes de code peut également être gracieuse :

your code: print('hi')
hi

L'utilisateur saisit print('hi') en tant qu'entrée utilisateur. Ceci est pris comme une chaîne "print('hi')" , emballé dans le program variable, passée dans le exec(program) fonction et exécuté.

Fichier Python exec()

Comment exécuter un fichier dans un interpréteur Python ?

Vous pouvez utiliser le puissant one-liner suivant :

exec(open("filename.py").read())

Le exec() la fonction exécutera tout le contenu du fichier filename.py sur l'ordinateur sur lequel il est exécuté.

Pensez à ce que vous pourriez faire avec ça ! Quelqu'un pourrait déployer des projets entiers sur une autre machine s'il avait accès au exec() fonction sur une machine !

Python exec() Globaux

Par défaut, Python transmet tous les noms globaux, ceux que vous pouvez obtenir avec globals() —dans le exec() , vous pouvez donc utiliser des variables que vous avez définies en dehors du exec() fonction :

x = 'Alice'

program = '''
def f():
    print(x)

f()
'''

exec(program)
# 'Alice'

Le résultat de cette exécution est la chaîne 'Alice' sur votre coque. Cependant, la variable x est défini en dehors du programme, donc le exec() fonction a accès à tout l'état du programme.

Si vous ne souhaitez pas autoriser les utilisateurs du exec() Pour pouvoir accéder à l'ensemble de l'état du programme, vous pouvez écraser les noms globaux en fournissant votre dictionnaire personnalisé de noms et leurs valeurs.

Voici comment créer une table rase pour votre exec() exécution du programme :

x = 'Alice'

program = '''
def f():
    print(x)

f()
'''

exec(program, dict())

La sortie est maintenant :

Traceback (most recent call last):
  File "C:\Users\xcent\Desktop\Finxter\Blog\HowToConvertBooleanToStringPython\code.py", line 14, in <module>
    exec(program, dict())
  File "<string>", line 6, in <module>
  File "<string>", line 3, in f
NameError: name 'x' is not defined

La raison de ce NameError est que la variable globale x ne fait pas partie du nouvel espace de noms global car vous avez passé le dictionnaire vide en tant que globals argument dans le exec() fonction.

Python exec() Locals

De la même manière, vous pouvez passer un dictionnaire comme deuxième argument au exec() pour personnaliser l'utilisation de votre espace de noms local. Sinon, Python utilisera simplement l'espace de noms global par défaut de votre programme comme espace de noms local.

Cela génère une NameError car la variable x n'existe pas dans l'espace de noms global et n'est donc pas visible dans la définition de la fonction :

x = 'Alice'

program = '''
def f():
    print(x)


f()
'''


exec(program, dict(), {'x':42})

Cependant, si vous utilisez la variable x dans un contexte local au sein de votre chaîne de programme, cela fonctionne !

x = 'Alice'
program = 'print(x)'
exec(program, dict(), {'x':42})
# OUTPUT: 42

La même sélection du dictionnaire global vide (premier argument) et du dictionnaire local (deuxième argument) avec la définition de la variable x conduit à un résultat radicalement différent lors de l'accès à x dans différents espaces de noms.

Python exec() contre eval()

exec() de Python La fonction prend un programme Python, sous forme de chaîne ou d'objet exécutable, et l'exécute. Le eval() La fonction évalue une expression et renvoie le résultat de cette expression. Il existe deux différences principales :

  • exec() peut exécuter tout le code source Python, alors que eval() ne peut évaluer que des expressions.
  • exec() renvoie toujours None , alors que eval() renvoie le résultat de l'expression évaluée.
exec('x=2;y=2;z=x*y;print(z)')
# 4

print(eval('2*2'))
# 4

Importer Python exec()

Pouvez-vous importer d'autres bibliothèques ou modules dans un exec() exécution? La réponse est oui! Appelez simplement le exec('import xxx; ...') pour importer la bibliothèque xxx dans l'espace de noms local du exec calcul.

program = '''
import random
print(random.randint(0,9))
'''

exec(program)
# Example Output: 2

Dans mon exécution, la sortie était 2 mais ce sera différent dans votre cas en raison de la nature de la fonction aléatoire. Le fait est que vous pouvez importer toutes les bibliothèques Python standard dans un exec() fonction en utilisant le standard import xxx motif.

Cela fonctionne également si vous utilisez le module random dans une autre portée (comme dans une fonction) :

program = '''
import random
def f():
    print(random.randint(0,9))
f()
'''

exec(program)
'''
4
'''

Python exec() plusieurs lignes

Vous pouvez simplement exécuter le exec() fonction sur plusieurs lignes de code Python en utilisant l'opérateur point-virgule pour séparer les instructions :

# Instead of ...
a = 2
b = 4
c = b/a
print(c)

# Write ...
exec('a=2;b=4;c=b/a;print(c)')

Cela ne fonctionne que s'il n'y a pas de blocs de code indentés tels que des définitions de fonction ou des instructions if. S'il y en a, utilisez simplement une chaîne multiligne :

program = '''
a = 2
b = int(input('your number: '))
if b>a:
    print('Yes!')
'''

exec(program)

Une manière moins pythonique consiste à utiliser le '\n' caractère au lieu des nouvelles lignes pour économiser de l'espace.

program = "a = 2\nb = int(input('your number: '))\nif b>a:\n    print('Yes!')"
exec(program)

Résumé

exec() de Python La méthode exécute le code Python que vous transmettez en tant qu'argument de chaîne ou d'objet exécutable.

>>> exec('x=2; y=4; print(x+y)')
6

C'est ce qu'on appelle l'exécution dynamique car, contrairement à la norme statique Code Python, vous pouvez générer du code et l'exécuter lors de l'exécution. De cette façon, vous pouvez exécuter du code Python créé par programme.

Veillez à ne pas autoriser des personnes non autorisées à exécuter le exec() de Python sur un shell Python sur votre ordinateur ou votre serveur car il ouvre toutes sortes de failles de sécurité.

Humour nerd

J'espère que vous avez apprécié l'article! Pour améliorer votre formation Python, vous pouvez rejoindre la populaire et gratuite Finxter Email Academy :


Voulez-vous améliorer vos compétences Python d'une manière amusante et facile à consommer ? Considérez les ressources suivantes et devenez un maître codeur !