Maison > développement back-end > Tutoriel Python > Comment créer votre propre Shell avec Python (Partie 2)

Comment créer votre propre Shell avec Python (Partie 2)

巴扎黑
Libérer: 2017-03-18 11:54:37
original
1194 Les gens l'ont consulté

Dans l'article précédent, nous avons créé une boucle principale du shell, divisé l'entrée de la commande et exécuté la commande via fork et exec. Dans cette partie, nous aborderons les problèmes restants. Tout d'abord, la commande cd test_dir2 ne peut pas modifier notre répertoire courant. Deuxièmement, nous ne pouvons toujours pas sortir gracieusement du shell.

Étape 4 : Commandes intégrées

"cd test_dir2 ne peut pas modifier notre répertoire actuel" Cette phrase est correcte, mais elle est également fausse dans un sens. C'est correct dans le sens où nous sommes toujours dans le même répertoire après avoir exécuté la commande. Cependant, le répertoire a effectivement été modifié, mais il a été modifié dans le processus enfant.

N'oubliez pas que nous avons créé un processus enfant, puis exécuté la commande. Le processus d'exécution de la commande ne s'est pas produit sur le processus parent. Le résultat est que nous modifions uniquement le répertoire courant du processus enfant, pas le répertoire du processus parent.

Ensuite, le processus enfant se termine, tandis que le processus parent continue de s'exécuter dans le répertoire intact.

Par conséquent, ces commandes liées au shell lui-même doivent être des commandes intégrées. Il doit être exécuté dans le processus shell et non en forking.

cd

Commençons par la commande cd.

Nous créons d'abord un répertoire builtins. Chaque commande intégrée sera placée dans ce répertoire.

yosh_project
|-- yosh
   |-- builtins
   |   |-- __init__.py
   |   |-- cd.py
   |-- __init__.py
   |-- shell.py
Copier après la connexion

Dans cd.py, nous implémentons notre propre commande os.chdir en utilisant l'appel système cd.

import os
from yosh.constants import *
def cd(args):
    os.chdir(args[0])
    return SHELL_STATUS_RUN
Copier après la connexion

Notez que nous renverrons l'état d'exécution du shell à partir de la fonction intégrée. Ainsi, pour pouvoir continuer à utiliser les constantes dans le projet, nous les avons déplacées vers yosh/constants.py.

yosh_project
|-- yosh
   |-- builtins
   |   |-- __init__.py
   |   |-- cd.py
   |-- __init__.py
   |-- constants.py
   |-- shell.py
Copier après la connexion

Dans constants.py, nous mettons ici toutes les constantes d'état.

SHELL_STATUS_STOP = 0
SHELL_STATUS_RUN = 1
Copier après la connexion

Maintenant, notre cd intégré est prêt. Modifions shell.py pour gérer ces fonctions intégrées.

...
### 导入常量
from yosh.constants import *
### 使用哈希映射来存储内建的函数名及其引用
built_in_cmds = {}
def tokenize(string):
    return shlex.split(string)
def execute(cmd_tokens):
    ### 从元组中分拆命令名称与参数
    cmd_name = cmd_tokens[0]
    cmd_args = cmd_tokens[1:]
    ### 如果该命令是一个内建命令,使用参数调用该函数
    if cmd_name in built_in_cmds:
        return built_in_cmds[cmd_name](cmd_args)
    ...
Copier après la connexion

Nous utilisons une variable de dictionnaire Python built_in_cmds comme carte de hachage pour stocker nos fonctions intégrées. Nous extrayons le nom et les paramètres de la commande dans la fonction execute. Si la commande se trouve dans notre table de hachage, la fonction intégrée correspondante est appelée.

(Astuce : built_in_cmds[cmd_name] renvoie une référence de fonction qui peut être appelée directement avec des arguments.)

Nous sommes presque prêts à utiliser la fonction cd intégrée. La dernière étape consiste à ajouter la fonction cd au mappage built_in_cmds.

...
### 导入所有内建函数引用
from yosh.builtins import *
...
### 注册内建函数到内建命令的哈希映射中
def register_command(name, func):
    built_in_cmds[name] = func
### 在此注册所有的内建命令
def init():
    register_command("cd", cd)
def main():
    ###在开始主循环之前初始化 shell
    init()
    shell_loop()
Copier après la connexion

Nous définissons la fonction register_command pour ajouter une fonction intégrée à notre carte de hachage de commande intégrée. Ensuite, nous définissons la fonction init et enregistrons ici la fonction cd intégrée.

Faites attention à cette ligne register_command("cd", cd) . Le premier paramètre est le nom de la commande. Le deuxième paramètre est une référence de fonction. Afin de permettre au deuxième paramètre cd de faire référence à la référence de la fonction yosh/builtins/cd.py dans cd, il faut placer la ligne de code suivante dans le fichier yosh/builtins/__init__.py.

from yosh.builtins.cd import *
Copier après la connexion

Ainsi, dans yosh/shell.py , lorsque nous importons yosh.builtins depuis * , nous pouvons obtenir la référence de fonction yosh.builtins qui a été importée via cd .

Nous avons le code prêt. Essayons d'exécuter notre shell, yosh, en tant que module dans le même répertoire que python -m yosh.shell.

Maintenant, la commande cd modifie correctement notre répertoire shell, tandis que les commandes non intégrées fonctionnent toujours. très bien!

sortir

La pièce finale est enfin là : sortez avec grâce.

Nous avons besoin d'une fonction qui puisse modifier l'état du shell en SHELL_STATUS_STOP . De cette façon, la boucle du shell peut se terminer naturellement, et le shell atteindra la fin et sortira.

est identique à cd Si nous forkons et exécutons la fonction exit dans le processus enfant, cela n'aura aucun effet sur le processus parent. Par conséquent, la fonction exit doit être une fonction intégrée au shell.

Commençons ici : créez un nouveau fichier appelé builtins dans le répertoire exit.py.

yosh_project
|-- yosh
   |-- builtins
   |   |-- __init__.py
   |   |-- cd.py
   |   |-- exit.py
   |-- __init__.py
   |-- constants.py
   |-- shell.py
Copier après la connexion

exit.py définit une fonction exit, qui renvoie uniquement un statut pouvant sortir de la boucle principale.

from yosh.constants import *
def exit(args):
    return SHELL_STATUS_STOP
Copier après la connexion

Ensuite, on importe la référence de la fonction yosh/builtins/__init__.py située dans le fichier exit.

from yosh.builtins.cd import *
from yosh.builtins.exit import *
Copier après la connexion

Enfin, nous enregistrons la commande shell.py dans la fonction init(). exit

...
### 在此注册所有的内建命令
def init():
    register_command("cd", cd)
    register_command("exit", exit)
...
Copier après la connexion
Ça y est !

Essayez d'exécuter python -m yosh.shell. Vous pouvez maintenant taper exit pour quitter le programme en douceur.

Pensées finales

J'espère que vous avez apprécié sa création autant que moi yosh (votrenotre >ell) processus. Mais ma version de en est encore à ses débuts. Je n'ai pas traité de certains cas de coin qui feraient planter la coque. Il existe de nombreuses commandes intégrées que je n'ai pas abordées. Pour améliorer les performances, certaines commandes non intégrées peuvent également être implémentées en tant que commandes intégrées (pour éviter le temps de création de nouveaux processus). Dans le même temps, un grand nombre de fonctionnalités n’ont pas encore été implémentées. J'ai fourni le code source sur https://github.com/supasate/yosh. N'hésitez pas à créer une fourchette et à l'essayer. yoshIl est maintenant temps de créer une coque qui vous ressemble vraiment.

Bon codage !

Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!

Étiquettes associées:
source:php.cn
Déclaration de ce site Web
Le contenu de cet article est volontairement contribué par les internautes et les droits d'auteur appartiennent à l'auteur original. Ce site n'assume aucune responsabilité légale correspondante. Si vous trouvez un contenu suspecté de plagiat ou de contrefaçon, veuillez contacter admin@php.cn
Tutoriels populaires
Plus>
Derniers téléchargements
Plus>
effets Web
Code source du site Web
Matériel du site Web
Modèle frontal