pyxshell : piper des flux de texte en pur Python

Posté par (page perso) . Édité par Davy Defaud, Benoît Sibaud, Xavier Claude, Xavier Teyssier et Nÿco. Modéré par Xavier Claude. Licence CC by-sa
33
16
jan.
2013
Python

pyxshell (à prononcer comme vous pouvez) est un module Python qui permet d’enchaîner des fonctions de traitement de flux avec un opérateur « tube » — pipe, en anglais — (|) , de la même manière qu’avec un shell.

Si — comme moi — vous devez régulièrement analyser à la main des données textuelles diversement structurées sous différents environnements. Si vous affectionnez la ligne de commande sans raffoler de la syntaxe de Bash, vous apprécierez d’avoir tout sous la main à côté de vos outils Python favoris.

Par exemple :

>>> out=[]
>>> (random.randint(0,2) for i in range(10)) | map(lambda x: ["Oui ","nous sommes ","tous différents "][x]) | sort | uniq | tee(sys.stdout) > out
Oui tous différents nous sommes
>>> print(out)
['Oui ', 'tous différents ', 'nous sommes ']

Dit autrement, pyxshell permet d’appeler séquentiellement des générateurs sur des structures de données itérables avec une notation infixée. Il descend du ciel avec un ensemble de fonctions qui rappellent celles de la pile GNU, principalement pour traiter des versets textuels ligne par ligne.

Le module permet une redirection des flux vers des fichiers et/ou des variables à l’aide des vénérables opérateurs > et >>. Il permet également d’étendre l’utilisation des tubes à vos glorieuses fonctions, à l’aide d’un décorateur consacré : @pipe. Il dispose en sus d’augustes opérateurs permettant de combiner des flux (avec +) ou d’en faire le produit cartésien de leurs bienheureux éléments (avec *).

pyxshell vous est révélé sous la « (Un)license ».

D’autres exemples tirés des écritures :

>>> import sys
>>> from pyxshell.common import *
>>> list( ['Vous', 'êtes', 'tous','des','individus'] | grep(r'[aeo]') )
['Vous', 'êtes', 'tous', 'des']
>>> ["Je dis que vous êtes le Messie","Et je m'y connais","J'en ai suivi un paquet"] | map(lambda x: "— "+x+"\n") | grep("'") | cut([-2,-1]) | traverse | glue > sys.stdout
m'y connais un paquet

Pour les mécréants qui voudraient utiliser leurs commandes shell de la même façon, depuis un interpréteur, mais sans avoir à utiliser des ré‐implémentations en pur Python, le module Plumbum leur conviendra mieux.

  • # Joli!

    Posté par (page perso) . Évalué à  2 .

    Dans la même idée, j'ai crée https://chut.readthedocs.org/en/latest/ Qui est grosso modo un wrapper à subprocess qui permet de lancer des commandes shell de façon pythonique et d'utiliser les pipe unix, aussi de facon pythonique.

    Ca se recoupe un peu. Sauf que pyxshell a fait le choix de manipuler du python, et chut de laisser faire les outils système.

    En tout cas, j'aime l'api :)

    • [^] # Re: Joli!

      Posté par (page perso) . Évalué à  5 .

      Comme dit dans la dépêche, Plumbum fait la même chose que chut, mais par dessus le module sh, qui utilise un hack très élégant pour l'import des commandes shell sous la forme de fonction. L'API est uber-cool, tu peux appeler les commandes sans même voir que c'est de l'appel système :

      >>> from plumbum.cmd import cat, head
      >>> ((cat < "setup.py") | head["-n", 4])()
      
      

      Tu devrais regarder leur code pour simplifier l'appel de tes commandes dans chut ;-)

  • # Coquille

    Posté par (page perso) . Évalué à  1 .

    s/prononcez/prononcer

  • # Lazy ?

    Posté par (page perso) . Évalué à  2 .

    Je n'ai pas vu dans la doc si c'étais lazy ou non (c'est à dire, comme dans vrai pipe unix, attend que la sortie soit traitée avant de prendre la prochaine entrée).

    En tout cas l'utilisation du | pour traiter les données en séquence est vraiment bien trouvée, ça fait partie des choses qui changent la manière dont on écrit le code…

    • [^] # Re: Lazy ?

      Posté par (page perso) . Évalué à  2 .

      Les commandes sont implémentées comme des générateurs (cf. la doc sur yield), donc la chaîne complète forme une fonction, qui s'exécute en entier tant que l'itérable passé a qqchose à envoyer (et qu'il n'y a que des générateurs dans la séquence). Donc, sur des traitements long, tu verras les lignes s'afficher au fur et à mesure.

      Dans l'exemple suivant, la fonction sleep ne fait qu'attendre avant de passer le prochain item, et les chiffres s'affichent bien au fur et à mesure :

      >>> import time
      >>> from pyxshell.common import *
      >>> @pipe
      def sleep(stdin,t):
          for i in stdin:
         ...:         time.sleep(t)
         ...:         yield i
         ...:         
      >>> for i in ( range(3) | sleep(1) ):
          print(i)
         ....:     
      0
      1
      2
      
      
    • [^] # Re: Lazy ?

      Posté par . Évalué à  2 .

      Est-ce fondamentalement différent de faire:

      data | operation1 | operation2 | operation3
      
      

      plutôt que:

      data.operation1().operation2().operation3()
      
      

      La deuxième est plus "pythonesque", et demanderait de créer une classe de donnée possédant les différentes opérations que l'on désire piper, plutôt que de créer des fonction indépendantes qui soient "pipables".

      • [^] # Re: Lazy ?

        Posté par (page perso) . Évalué à  3 .

        En fait, si on prend l'exemple des listes donné dans la dépêche, la syntaxe en pipe est plutôt équivalente à :

        operation3 ( operation2 ( operation1 ( data ) ) )
        
        

        et là, la différence est claire, les pipes sont beaucoup plus lisibles pour moi…

        • [^] # Re: Lazy ?

          Posté par . Évalué à  6 .

          Nom de Zeus, nous avons ressuscité le LISP!!!!

        • [^] # Re: Lazy ?

          Posté par (page perso) . Évalué à  7 .

          Je ne sais pas si vous vous en rendez compte, mais c'est un vieux troll, qui a eu ses beaux jours à l'arrivée de la POO.

          De fait, les différentes syntaxes sont équivalentes, mais il y en a d'autres, aussi… quelques exemples :

          data | op1 | op2(arg) | op3 > var         # style shell infixé
          var = Pipe(data).op1().op2(arg).op3()     # style POO
          var << Pipe(data)->op1()->op2(arg)->op3() # style WTFOO
          var := op3(op2(op1(data),arg))            # style fonctionnel préfixé
          var <- op3 $ op2 $ arg op1 $ data         # style fonctionnel infixé
          var = (data op1) arg op2 op3              # style fonctionnel postfixé
          etc. ?
          
          

          Personnellement, j'ai l'habitude de traiter les flux en shell, et j'aime bien que le traitement se lise de gauche à droite, sans fioritures. D'ailleurs, je me garderais bien de décréter que tel ou tel style est le plus pythonique dans ce cas précis. le fait est que l'infixé avec pipe me parait à la fois plus concis, plus intuitive et est plus simple à implémenter. CQFD.

          • [^] # Re: Lazy ?

            Posté par . Évalué à  1 .

            En fait, pour voir les pipes comme plus pythonique, il faut comprendre le | comme un opérateur. Or a | b est équivalent à a.__or__(b). On peut donc facilement définir les pipes par:

            class Pipe(float):
                def __or__(self, val):
                    return Pipe(self(val))
            
            

            Ce qui peut être utilisé ainsi:

            def f(x):
                return x+1
            
            def g(x):
                return x*x
            
            print Pipe(4) | f | f | g
            >>> 36
            
            

            Intéressant :-)

            • [^] # Re: Lazy ?

              Posté par . Évalué à  2 .

              Il fallait bien sur lire:

              class Pipe(float):
                  def __or__(self, val):
                      return Pipe(val(self))
              
              
          • [^] # Re: Lazy ?

            Posté par . Évalué à  2 .

            Une chose que je note: il y a 3 styles qui sont "cohérent":le "style shell infixé" (se lit de gauche à droite) et lex "style shell préfixé/infixé" (se lisent de droite à gauche), les autres c'est le bazar..

            Le premier a l'avantage pour nous Français d'être dans l'ordre "normal" mais l'inconvénient que 'var' doit soit existé déjà soit être déclarée automagiquement, autrement on se retrouve avec une notation un peu bizarre:
            "op1 | op2 > var res:Result".

            Le style fonctionnel préfixé est un peu lourd avec les parenthèses(*), le infixé est pas mal, mais le '$' ne donne pas le sens de lecture donc on pourrait avoir:
            var <- op3 <- op2 <- arg op1 <- data
            L'espace pour séparer les arguments d'une fonction c'est élégants pour les lignes courtes mais difficile a lire quand ça devient complexe:
            var <- op3 <- op2(arg, op1 data)

            C'est quoi le nom du style suivant:
            var res <- op3 <- op2(arg) <- op1 <- data
            WTFFunc?

            *: par contre l'ordre dans l'exemple me parait incorrecte ce serait plutôt
            var := op3(op2(arg,op1(data)))

            • [^] # Re: Lazy ?

              Posté par (page perso) . Évalué à  2 .

              WTFOO : What The Fuck Object Oriented. C'est une vanne sur la lourdeur syntaxique du C++.

              Pour des exemples d'opérateur $, voir le langage fonctionnel Haskell.

              Je me garderais bien de donner un avis tranché sur l'élégance, quant à moi :-)

      • [^] # Re: Lazy ?

        Posté par . Évalué à  4 .

        De ce que je comprends:
        dans

        data | operation1 | operation2 | operation3
        
        

        il y a 3 threads qui traitent les données, en parallèle, au fur et à mesure qu'elle sont disponible.

        dans

        data.operation1().operation2().operation3()
        
        

        il y a une thread qui traite les données, opération par opération, par ensemble complet.

        Si c'est bien le cas, l'utilisation des ressources CPU+RAM est totalement différente.

        Me trompe-je ?

    • [^] # Re: Lazy ?

      Posté par (page perso) . Évalué à  2 .

      En tout cas l'utilisation du | pour traiter les données en séquence est vraiment bien trouvée,

      C'est quand même pas une idée très originale, si?

      ça fait partie des choses qui changent la manière dont on écrit le code…

      Si tu utilises un langage de programmation fonctionnelle, pas trop, puisque l'opérateur de pipe est un opérateur de composition de fonctions (avec un sens de lecture inversé).

      Cf. par exemple la fonction Shell.call de la bibliothèque OCamlnet: http://projects.camlcity.org/projects/dl/ocamlnet-3.6.3/doc/html-main/Shell.html

      • [^] # Re: Lazy ?

        Posté par (page perso) . Évalué à  2 .

        Si tu utilises un langage de programmation fonctionnelle, pas trop, puisque l'opérateur de pipe est un opérateur de composition de fonctions (avec un sens de lecture inversé).

        J'ai pris l'habitude d'utiliser le |> de batteries qui permet de composer les fonctions de cette manière.

        Par contre il faut reconnaître que l'on ne voit pas souvent de composition de fonction dans les langages non fonctionnels (ok, python est un peu à part), et c'est dommage. C'est dans ce sens ou je dis que ça change la manière d'écrire le code, on change de paradigme : on n'est plus en train d'appliquer une méthode à objet, mais on prend un objet dans un contexte, et on lui applique une série de traitement pour le transformer en un autre objet.

        Bon je m'arrête là car ça n'est pas le sujet de la dépêche, et l'on parle de la même chose…

  • # Licence

    Posté par (page perso) . Évalué à  4 .

    Il n'est pas possible en France de placer une œuvre dans le domaine public, mais si tu veux t'en approcher autant que possible, la CC0 serait peut-être plus appropriée.

    https://creativecommons.org/choose/zero/

    • [^] # Re: Licence

      Posté par (page perso) . Évalué à  6 .

      Il n'est pas possible en France de placer une œuvre dans le domaine public

      Quand on dit « en France », on parle de quoi exactement ? De la nationalité de l'auteur ? Du lieu de résidence de l'auteur ? Du lieu où a été créée l'œuvre ? Du lieu où celle-ci a été publiée (en l'occurrence le serveur de github, USA) ?

      • [^] # Re: Licence

        Posté par . Évalué à  2 .

        Dans les cas où la loi française s'applique.
        Je pense (mais je ne suis pas juriste) qu'il faut et qu'il suffit qu'une partie significative du processus de création de l'œuvre de l'esprit (= le développement) aie lieu en France. Ça inclut les DOM/TOM, les eaux territoriales et les ambassades et consulats.
        La nationalité de l'auteur n'a je pense aucune incidence, pas plus que sa résidence (sauf si c'est le lieu de création) ou les différents lieux, moyens et intermédiaires de publication.

        En même temps pour du logiciel, la différence entre CC0, domaine public ou MIT n'est pas hyper flagrante dans ses effets.

        • [^] # Re: Licence

          Posté par (page perso) . Évalué à  2 .

          Je pense (mais je ne suis pas juriste) qu'il faut et qu'il suffit qu'une partie significative du processus de création de l'œuvre de l'esprit (= le développement) aie lieu en France. Ça inclut les DOM/TOM, les eaux territoriales et les ambassades et consulats.

          Non pas du tout. Au regard du droit français ou européen, il faut écrire dans le contrat de licence quel droit s'applique. La GPL ne le fait pas, ceci est présenté comme une vulnérabilité de la licence par les juristes qui ont concocté les licences CeCILL.

          http://www.cecill.info/faq.fr.html#international

          • [^] # Re: Licence

            Posté par . Évalué à  1 .

            On peut préciser une juridiction dans un contrat, c'est d'ailleurs exactement ce que dit le lien que tu cites.

            Et je me permets de remarquer que la question portait sur le domaine public, lequel ne fait justement pas l'objet de contrat, ce qui laisse peu d'endroit ou écrire une clause d'attribution de compétence…

    • [^] # Re: Licence

      Posté par (page perso) . Évalué à  1 .

      Cependant ce paragraphe seul a le même effet qu'une licence BSD/MIT/etc.

      Anyone is free to copy, modify, publish, use, compile, sell, or
      distribute this software, either in source code form or as a compiled
      binary, for any purpose, commercial or non-commercial, and by any
      means.

      Du coup, je trouve ça plutôt intéressant, même dans un pays où le reste n'est pas possible. Cela semble voulu : http://ar.to/2010/01/dissecting-the-unlicense

  • # Amis lusitaniens…

    Posté par (page perso) . Évalué à  1 . Dernière modification : le 16/01/13 à 18:47

    Un bel exemple de projet made in Portugal !

  • # pypi

    Posté par (page perso) . Évalué à  2 .

    La documentation mentionne pypi et pip, mais je ne vois rien sur https://pypi.python.org/pypi/pyxshell.

    Sinon, est-ce que comme github l'indique, c'est un fork de calabash ? Pourquoi avoir renommé la chose, c'est devenu incompatible ?

    • [^] # Re: pypi

      Posté par (page perso) . Évalué à  2 .

      C'est encore la doc de calabash, je n'ai pas encore pris le temps de soumettre ça sur pypi.

      C'est un fork plus ou moins compatible (calabash n'est pas en python3, mais sinon c'est juste une extension). Les explications sur le changement de nom sont dans mon premier commit.
      En gros, calabash était déjà très googlé et pas très vendeur.

      • [^] # Re: pypi

        Posté par (page perso) . Évalué à  1 .

        OK. Note que publier sur pypi, c'est ./setup.py sdist register upload et hop :)
        Pour packager/installer automatiquement la chose c'est plus pratique qu'un snapshot github.

        C'est vrai que j'ai toujours été étonné par le peu de popularité de calabash… j'espère que ça changera avec un nouveau nom, mainteneur et le support de Python 3 !

  • # À coupler avec pysh ?

    Posté par (page perso) . Évalué à  2 .

    Ave,

    Encore un gros bravo pour ce projet original et astucieux !

    Jusqu'à présent, j'utilise sh , mais je suis frustré par sa gestion des entrée/sortie. Parcontre, j'aime bien sa génération automatique de commande shell. Utiliser dmsetup en python, c'est trop pratique !

    Il semble que ce chut fournisse les deux fonctionnalités.

    • [^] # Re: À coupler avec pysh ?

      Posté par (page perso) . Évalué à  1 .

      Je me réponds à moi-même. Comme le dit la dépêche, plumbum est ce que je cherche. Même s'il manque la partie itérateur.

      Est-ce possible d'avoir une gestion générique d'itération sur les lignes (façon xargs) sur les commandes SH ?

      • [^] # Re: À coupler avec pysh ?

        Posté par (page perso) . Évalué à  1 .

        Avec Plumbum, je ne sais pas trop, mais avec chut ou pyxshell, c'est trivial, il suffit d'utiliser map avec une fonction (lambda, par exemple).

        Ça devrait être un truc du genre :

        ls("-l") | map( lambda x : rm(x) )
        
        
  • # Ajouter un contexte ?

    Posté par (page perso) . Évalué à  7 .

    Pour pouvoir écrire:

    with sudo('root'):
        cd('/')
        ls("-l") | map( lambda x : rm(x) )
    
    

    :-)

    • [^] # Re: Ajouter un contexte ?

      Posté par (page perso) . Évalué à  3 .

      Ça permettrais des écritures plus simples et sécurisées sur d'autres choses.

      Par exemple le changement temporaire de répertoire:

      with cd('/etc/apache2'):
          mv('machin.cfg', 'machinold.cfg')
          with open('machin.cfg',"w") as f:
              f.write('#!/bin/sh\necho "Coucou"')
      
      

      Et quand on sort du bloc, on revient dans le répertoire précédent.

      • [^] # Re: Ajouter un contexte ?

        Posté par . Évalué à  3 .

        C'est inspiré de ce que propose fabric ? Une brève histoire de context

        Je suis dans ma tour d'ivoire (rien à foutre des autres, dites moi un truc pour moi), si je ne pose pas explicitement une question pour les 99%, les kévin, les Mm Michu alors c'est que je ne parle pas d'eux.

  • # Switcher à python comme shell

    Posté par . Évalué à  2 .

    (ma vie) C'est marrant j'étais en train de me dire que je scriptai de plus en plus en python pour des trucs qui seraient faisable en shell. D'ailleurs j'étais même presque sur le point de tenter d'expérimenter un peu avec ipython comme shell principal, il manque pas grand chose à python pour faire office de shell un peu plus puissant que bash, avec moins d'ésotérisme dans la syntaxe, l'interprétation des variables, la cohérence du langage, la structuration des types …

    C'est d'autant plus tentant avec ce genre de projets qui complémentent bien les fonctionnalités d'ipython.

    Quelqu'un a des expériences avec ce genre de tentative ?

    • [^] # Re: Switcher à python comme shell

      Posté par . Évalué à  1 .

      C'est aussi mon rêve !
      On peut commencer par rester dans le shell et faire plus de choses en python, comme avec the Pyed Piper
      https://code.google.com/p/pyp/
      puis passer à la console Qt de ipython
      http://ipython.org/ipython-doc/stable/interactive/qtconsole.html
      elle est pas parfaite du tout pour le shell mais fait plutôt rêver.

    • [^] # Re: Switcher à python comme shell

      Posté par (page perso) . Évalué à  2 .

      Quelqu'un a des expériences avec ce genre de tentative ?

      Je te le déconseille fortement.

      Je connais très bien la programmation en Bourne shell pourtant mon shell intéractif est TCSH. La raison? Je ne sais pas programmer TCSH, donc je n'écris pas de ligne de commande imbitable.

      Si j'ai quelque chose de compliqué à faire j'ouvre mon éditeur et je l´écris, et je le relis. Cela ne prend pas plus de temps et je fais moins de faute parceque mon programme jetable est mieux présenté, colorié et tout. ET c'est plus facile d'insérer une fonction intermédiaire si je décide que mon programme en serait plus facile à écrire — chose que tu ne feras jamais en ligne de commande.

      Je te conseille de faire la même chose: si tu adores décrire tes tâches en Python pourquoi le faire dans un interpréteur plutôt que dans un éditeur de texte?

      • [^] # Re: Switcher à python comme shell

        Posté par . Évalué à  4 .

        J'ai assez d'expérience pour savoir quand ça vaut le coup de dégainer l'éditeur de texte ou non, je trouve d'ailleurs avoir tendance à le faire un peu trop : tu fais un script que tu perds du temps à relire voire à génériciser excessivement pour une tâche qui ne mériterait même pas d'être scriptée, c'est presque une tendance dont j'aimerai me débarrasser.

        Du coup je suis pas du tout d'accord avec tes arguments. En plus si jamais au cours du codage tu changes d'avis et décide que finalement ce serait mieux de coder le truc, rien qu'en bash il y a un raccourcis pour ouvrir un éditeur de texte sur la commande que tu es en train d'écrire, et si ton shell est dans le même langage que le langage que tu utilises il y a toujours moyen de copier / coller le code. C'est aussi possible de décrire des fonctions simple de manière interractives, d'ailleurs.

        • [^] # Re: Switcherà pythoncomme shell

          Posté par (page perso) . Évalué à  2 .

          coder le truc, rien qu'en bash il y a un raccourcis pour ouvrir un éditeur de texte sur la commande que tu es en train d'écrire

          Qu'est ce ? Y-a t-il un equivalent pour zsh ?

        • [^] # Re: Switcher à python comme shell

          Posté par (page perso) . Évalué à  2 .

          tu fais un script que tu perds du temps à relire voire à génériciser excessivement pour une tâche qui ne mériterait même pas d'être scriptée,

          Ce dont je parle ce n'est ni de généreciser excessivement ni de passer 10 plombes à relire. Seulement, je trouve d'une part que même pour écrire une simple boucle for l'éditeur permet d'écrire plus proprement et de faire moins d'erreur; d'autre part que l'idiome classique SELECT | EDIT | PROCESS est plus clair quand on l'écrit avec trois fonctions. Donne un nom à un bloc de code en sh dure 1/2 seconde, surtout si on a déjà les noms.

          Par exemple pour renommer les fichiers selon un schéma à la noix SELECT utillise find pour trouver les noms des fichiers, EDIT produit des lignes vieux_nom|nouveau_nom et PROCESS renomme les fichiers (IFS).

      • [^] # Re: Switcher à python comme shell

        Posté par . Évalué à  4 .

        Si j'ai quelque chose de compliqué à faire j'ouvre mon éditeur et je l´écris, et je le relis. Cela ne prend pas plus de temps et je fais moins de faute parceque mon programme jetable est mieux présenté, colorié et tout. ET c'est plus facile d'insérer une fonction intermédiaire si je décide que mon programme en serait plus facile à écrire — chose que tu ne feras jamais en ligne de commande.

        Moi ça dépend, j'utilise un fichier uniquement si je veux réutiliser plusieurs fois l'algo. Je crée des commandes relativement complexes (utilisation de boucle, de variables, de fonctions, de l'historique et de substitution de processus) dans mon shell interactif (zsh). C'est généralement un peu moins propre (je me soucie peu de l'affichage tant que moi j'arrive à lire) car ce n'est jamais distribué. C'est très souvent des algo réellement jetables, je ne m'en resert jamais.

        Toute fois je suis d'accord pour dire que c'est moin agréable d'éditer ça de manière interactive. bash possède pour ça une parade Ctrl+x Ctrl+e pour ouvrir la commande courante dans un éditeur ($EDITOR). Je ne doute pas que zle (le readline de zsh) doit le permettre mais pour le moment je n'ai ni trouvé ni cherché.

        Je suis dans ma tour d'ivoire (rien à foutre des autres, dites moi un truc pour moi), si je ne pose pas explicitement une question pour les 99%, les kévin, les Mm Michu alors c'est que je ne parle pas d'eux.

        • [^] # Re: Switcher à python comme shell

          Posté par (page perso) . Évalué à  2 .

          C'est très souvent des algo réellement jetables, je ne m'en resert jamais.

          Pour un traitement complexe, meme si je ne m'en sers qu'une fois, j'utilise un fichier. Cela évite de faire des erreurs, et rend l'édition plus facile.

          Toute fois je suis d'accord pour dire que c'est moin agréable d'éditer ça de manière interactive. bash possède pour ça une parade Ctrl+x Ctrl+e pour ouvrir la commande courante dans un éditeur ($EDITOR).

          Comme j'utilise TCSH, je ne réfléchis pas. S'il y a un risque de boucle for, j'utilise l'éditeur. Ne pas réfléchir, cela fait gagner du temps. :) (Dans ce cas là bien-sûr!)

          Je ne cherche pas à en faire une position de principe: chacun fait au final comme il veut. Pendant longtemps je jouais au Samouraï de la ligne de commande, j'avoue que j'en tirais parfois une petite fierté. Mais un jour sur la ML de FreeBSD j'ai lu le témoignage de quelqu'un présentant le point de vue que je défends aujourd'hui. L'argument que TCSH est une horreur à programmer et que c'est exactement la raison qui en fait le meilleur SHELL intéractif m'a paru saugrenu. Cependant, j'ai essayé et je ne suis jamais revenu en arrière. L'intérêt principal étant d'éviter de se poser la question «éditeur ou pas?».

      • [^] # Re: Switcher à python comme shell

        Posté par . Évalué à  5 .

        Si j'ai quelque chose de compliqué à faire j'ouvre mon éditeur et je l´écris, et je le relis. Cela ne prend pas plus de temps et je fais moins de faute parceque mon programme jetable est mieux présenté, colorié et tout. ET c'est plus facile d'insérer une fonction intermédiaire si je décide que mon programme en serait plus facile à écrire — chose que tu ne feras jamais en ligne de commande.

        Ben justement ipython te permet de commencer à faire du script interactif en quelques lignes puis si ça commence à devenir trop gros, un simple %save mon_script 1-num_dernière_ligne et roule ma poule !

        Si on a plein de lignes à taper, un petit %edit, ça ouvre ton éditeur favoris, tu tapes, c'est plein de jolies couleurs, tu fermes en sauvegardant, puis ça exécute !

        Dans ipython tu peux aussi écrire en tout ce que tu aurais pu écrire sur ton shell, simplement précéder la commande de !

        Bref, c'est une habitude à prendre, mais je sais que mon ipython me sert souvent !

    • [^] # Re: Switcher à python comme shell

      Posté par . Évalué à  1 .

      Les vrais hommes utilisent brainfuck comme shell, pas python.
      ;-)

Suivre le flux des commentaires

Note : les commentaires appartiennent à ceux qui les ont postés. Nous n'en sommes pas responsables.