Journal Python à trou : trouve ton environnement

Posté par  (site web personnel) . Licence CC By‑SA.
Étiquettes :
8
17
fév.
2025

Demat'iNal

petit jeu : trouve une valeur de a pour laquelle la séquence suivante soit valide (au sens où elle s’exécute sans exception) :

>>> class a(*{++a},a=a--a): {}

Par exemple :

>>> a = 1
>>> class a(*{++a},a=a--a): {}
  File "<stdin>", line 1, in <module>
TypeError: int() takes at most 2 arguments (4 given)

n'est pas valide

  • # Errata (si un modo passe par là)

    Posté par  (site web personnel) . Évalué à 3 (+1/-0).

    >>> class a(*{++a},a=a--a): {}
  • # .

    Posté par  (site web personnel) . Évalué à 9 (+7/-0).

    je suis pas sûr d'avoir compris la question, mais j'ai pas d'erreur avec ce a là :

    >>> class b:
    ...     def __init__(self, *args, **kwargs):
    ...         pass
    ...     
    ...     def __sub__(self, o):
    ...         return self  
    ...     
    ...     def __pos__(self):
    ...         return self
    ...     
    ...     def __neg__(self):
    ...         return self
    ...     
    ... a = b()
    ...  
    ... class a(*{++a},a=a--a): {}
    ... 
    >>>
    • [^] # Re: .

      Posté par  . Évalué à 3 (+1/-0).

      Je suis egalement un peu perdu sur la question. En testant chatgpt en mode "reason", il arrive sur une solution similaire.

      Ca marche, mais je ne suis pas sur que ce soit l'exercice.

  • # sale type

    Posté par  . Évalué à 9 (+7/-0).

    a=type('',(),dict(__init__=lambda _,*a,**k:None,__pos__=lambda x:x,__neg__=lambda x:x, __sub__=lambda x,_:x))()
  • # Mais sinon, Perl c'est pas lisible.

    Posté par  . Évalué à 2 (+2/-2).

    Grmbl.

  • # Maintenant qu'on est vendredi...

    Posté par  . Évalué à 2 (+1/-1). Dernière modification le 21 février 2025 à 20:09.

    … je vous propose une variante, en shell bash1.

    Pour quelle valeur de a le code suivant se comporte-t-il correctement ?

    ~$ a=16
    ~$ a(){ a|a& };a

    Question subsidiaire, mais je trouve bien plus intéressante et moins potache : pourquoi le code suivant, dont les seules différences sont les espaces dans les accolades, produit-il une erreur ?

    ~$ a=16
    ~$ a(){a|a&};a
    bash: syntax error near unexpected token '{a'

    1. N'exécutez pas ce code. Ce message et son contenu sont fournis à titre éducatif, je ne suis responsable d'aucun de vos malheurs.  

    • [^] # Re: Maintenant qu'on est vendredi...

      Posté par  . Évalué à 6 (+4/-0).

      🎶 fork bomb, fork bomb, you're my fork bomb, na na na na nan 🎶

    • [^] # Re: Maintenant qu'on est vendredi...

      Posté par  . Évalué à 4 (+1/-0). Dernière modification le 23 février 2025 à 22:58.

      pourquoi le code suivant, dont les seules différences sont les espaces dans les accolades, produit-il une erreur ?

      Parce que le mot-clé { n’est pas reconnu comme tel sans cet espace ?

      Tu peux expliquer ce code?

      je dirais que tu déclare un variable a, et une fonction a que tu appelles ensuite. Cette fonction a() est récursive, le | est un pipe, le & exécute la commande en arrière plan. Je devine que c’est une fork bomb vu que tu préviens qu’il faut éviter de le lancer et vu le commentaire de la personne qui t’a répondu. Mais j’avoue que je comprends pas pourquoi ou comment ça marche. Naïvement j’aurais pensé qu’un truc comme a() { a & }; a suffirait. C’est pas vraiment le genre d’expérience que je tente. Quand une fork bombe explose chez moi c’était pas volontaire…

      J’ai même ces alias là dont je me sers parfois quand je développe certains scripts :

      $ alias ts ks
      alias ts='pkill -term -e -A -s $$'
      alias ks='pkill -kill -e -A -s $$'

      ^^

      • [^] # Re: Maintenant qu'on est vendredi...

        Posté par  (site web personnel) . Évalué à 9 (+6/-0).

        Sans le |, chaque a() lancé se termine au lancement du suivant : a1 lance a2 et se termine tandis que a2 lance a3 et se termine tandis que… tu occupes ton CPU (enfin sans doute un seul coeur au mieux) mais ce n'est pas un déferlement de processus. Maintenant si chaque a() en lance plusieurs, alors la croissance exponentielle du monde capitaliste rêvé se produit et le monde fini de la mémoire et de la table des processus sifflent la fin de la récré dans une agonie embourbée.

      • [^] # Re: Maintenant qu'on est vendredi...

        Posté par  . Évalué à 6 (+3/-0).

        Tu peux expérimenter avec des cgroups et des limites avec la commande systemd-run par exemple.

        Lancer un shell avec max 50 sous-processus :
        bash
        systemd-run --scope -p TasksMax=50 --pty bash

      • [^] # Re: Maintenant qu'on est vendredi...

        Posté par  . Évalué à 3 (+1/-0).

        pourquoi le code suivant, dont les seules différences sont les espaces dans les accolades, produit-il une erreur ?

        Parce que le mot-clé { n’est pas reconnu comme tel sans cet espace ?

        Oui, certainement, la question est pourquoi ce n'est pas reconnu. Sans doute un truc historique défini au néolithique et qu'on se traîne encore :).

        C'est amusant que bash ne sache pas s'en sortir sans les espaces. C'est un comportement plutôt rare dans les langages de programmation. Il y a la même chose avec l'opérateur [[ ]] :

        [[ $a -lt 10 ]] -> ok
        [[$a -lt 10]] -> erreur de syntaxe
        
        • [^] # Re: Maintenant qu'on est vendredi...

          Posté par  (site web personnel) . Évalué à 9 (+6/-0). Dernière modification le 26 février 2025 à 09:45.

          $ if [ -f /dev/null ] ; then echo OK ; fi
          $ if [-f /dev/null ] ; then echo OK ; fi
          [-f : commande introuvable

          Et la raison : dans le parcours du PATH, il ne trouve pas la commande. Il existe bien une commande '[' dans /usr/bin.

          -rwxr-xr-x 1 root root 55744 avril  5  2024 '/usr/bin/['

          Mais il n'existe pas de commande '[-f' dans /usr/bin (ou ailleurs dans le PATH)

          newfstatat(AT_FDCWD, "/usr/bin/[-f", 0x7fffa185f290, 0) = -1 ENOENT (Aucun fichier ou dossier de ce nom)

          (info tirée d'un strace sur un bash)

          -> l'espace est obligatoire dans ce cas car il faut séparer l'exécutable des arguments.

          Et [[ est une builtin du shell, mais [[-f ne l'est pas et donc il se rabat sur le PATH et il ne trouve pas :

          newfstatat(AT_FDCWD, "/usr/bin/[[-f", 0x7fffa185f290, 0) = -1 ENOENT (Aucun fichier ou dossier de ce nom)
          • [^] # Re: Maintenant qu'on est vendredi...

            Posté par  . Évalué à 4 (+2/-0).

            Merci ! Et donc la doc de [ se trouve dans la page de manuel de test.

            Truc marrant d'ailleurs, sur un terminal dans une VM Kali Linux, je regarde la page de man de test, et je vois des opérateurs comme , et . Je me dis tiens c'est moderne dis-donc, tiens (dis-donc).

            Et en passant le curseur dessus, et bien le ≠ se change en !=, et le en >=. Je n'avais jamais vu ça avant, c'est le terminal qui interprète les séquences. Je ne sais pas trop si j'aime ça dans le cadre de lecture de doc sur la syntaxe d'un commande, mais ça m'a intrigué :p.

            • [^] # Re: Maintenant qu'on est vendredi...

              Posté par  . Évalué à 5 (+3/-0).

              Ton terminal et la font que tu utilise supportent ce genre de ligatures

              https://github.com/tonsky/FiraCode?tab=readme-ov-file#whats-in-the-box

              https://linuxfr.org/users/barmic/journaux/y-en-a-marre-de-ce-gros-troll

            • [^] # Re: Maintenant qu'on est vendredi...

              Posté par  . Évalué à 6 (+3/-0). Dernière modification le 27 février 2025 à 20:13.

              page de manuel de test

              Je ne sais pas si tu connais mais il existe une commande interne, un builtin, nommé help.

              Personnellement c’est une chose que j’ai appris bien trop tard à mon goût, alors je tiens à en parler.

              Comme pour toute les commandes ayant une version interne au shell la page man (de test) indique :

              NOTE : votre interpréteur de commandes peut avoir sa propre version de test et/ou de [ qui remplace en général la version décrite ici. Veuillez vous référer à la documen‐
                     tation de votre interpréteur de commandes pour en connaître les options. 
              
              $ help help
              help: help [-dms] [motif ...]
                  Affiche des informations sur les commandes intégrées.
              
                  Affiche de courts résumés des commandes intégrées.  Si MOTIF est
                  spécifié, une aide détaillée de toutes les commandes correspondantes
                  au MOTIF est affichée, sinon la liste des sujets d'aide est affichée.
              
                  Options :
                    -d        affiche une courte description pour chaque sujet
                    -m        affiche l'aide dans un format proche des pages de man(uel)
                    -s        n'affiche qu'une courte aide pour chaque sujet correspondant au
                              MOTIF
              
                  Arguments :
                    MOTIF     Motif spécifiant un sujet d'aide
              
                  Code de retour :
                  Renvoie le code de succès à moins que le MOTIF ne soit pas trouvé ou qu'une
                  option non valable ne soit donnée.

              Note que tu peux faire appel au programme test qui est concerné par la page de manuel, soit en spécifiant tout le chemin : /usr/bin/test, soit en préfixant avec command (command test …).

              Les builtins se comportent grosso-modo pareil que la commande qu’ils remplacent (pour plus de performance en évitant un appel système gourmand), mais c’est plus ou moins vrai. Le builtin time de Bash et le programme /usr/bin/time, par exemple, sont très différents, l’un et l’autre ont leur intérêt respectif.

              Pour la commande help, si je peux éviter à des personnes des man bash | grep -C3 truc qui n’ont pour ma part que trop longtemps contrarié ma bonne santé capillaire, je suis content.

              • [^] # Re: Maintenant qu'on est vendredi...

                Posté par  (site web personnel) . Évalué à 6 (+3/-0).

                La commande test (et la builtin shell test) est un de mes plus mauvais souvenirs informatiques : il y a fort fort longtemps, j'avais écrit un test.c et compilé en gcc -o test test.c, et j'avais passé un bout de temps à essayer de comprendre pourquoi ça ne faisait pas du tout ce que je voulais quand je lançais test mes arguments. Et c'est ainsi que j'ai appris à ne plus jamais nommer mes programmes "test"…

                • [^] # Re: Maintenant qu'on est vendredi...

                  Posté par  . Évalué à 4 (+2/-0).

                  Ah ? Ça t'a pas vacciné à l'idée de mettre . dans ton PATH ?

                  https://linuxfr.org/users/barmic/journaux/y-en-a-marre-de-ce-gros-troll

                  • [^] # Re: Maintenant qu'on est vendredi...

                    Posté par  (site web personnel) . Évalué à 4 (+1/-0).

                    Pour ça j'ai appris à faire ./cmd plutôt. Ça évite de lancer des commandes qui traineraient au mauvais endroit.

                    • [^] # Re: Maintenant qu'on est vendredi...

                      Posté par  . Évalué à 3 (+1/-0).

                      et justement ça évite de confondre test et ./test.

                      https://linuxfr.org/users/barmic/journaux/y-en-a-marre-de-ce-gros-troll

                      • [^] # Re: Maintenant qu'on est vendredi...

                        Posté par  (site web personnel) . Évalué à 6 (+3/-0).

                        En contrepartie du fait que quand tu tapes test tu ne sais pas si tu lances le builtin test, /tmp/test, $HOME/bin/test, /usr/bin/test, /jenesaisquoi/test suivant là où tu trouves… Donc je préfère ne pas avoir . dans mon $PATH et taper ./test.

                        Ne pas appeler son binaire nommé "test" et avoir "." dans son $PATH ne sont pas deux questions se recouvrant avec exactement les mêmes problématiques :

                        • "./test" n'appelle jamais la builtin shell
                        • "test" avec "." dans le PATH appellera la builtin shell quand même
              • [^] # Re: Maintenant qu'on est vendredi...

                Posté par  . Évalué à 2 (+0/-0).

                Je ne sais pas si tu connais mais il existe une commande interne, un builtin, nommé help.

                Jusqu'à la lecture de ton message, je passais un temps fou à chercher le bon endroit dans la très longue page de man de bash, pour vérifier les options de commandes comme set ou read.

                Alors mille mercis !

                • [^] # Re: Maintenant qu'on est vendredi...

                  Posté par  . Évalué à 3 (+2/-0). Dernière modification le 02 mars 2025 à 00:48.

                  Bonjour

                  … je passais un temps fou à chercher le bon endroit dans la très longue page de man de bash …

                  Si le pager utilisé par la commande man sur votre système est less, vous pouvez utiliser ses fonctionnalités de recherche (et beaucoup d'autres).

                  Sur mon système debian, quand je lance la ligne de commande man bash, au bas de la page une ligne affiche le texte suivant :

                  Manual page bash(1) line 1 (press h for help or q to quit)

                  Alors j'ai appuyé sur la touche h et c'est la page d'aide en ligne du pager less qui s'affiche.

                  Dans cette première page d'aide, je peux lire que la touche q me permettra de quitter l'aide en ligne, et plus bas dans l'aide en ligne, je vois que je peux entrer un motif de recherche en le faisant précéder du caractère /.

                  Donc je tape q pour quitter l'aide en ligne et revenir dans le manuel de bash,
                  et j'entre le motif de recherche (précédé du caractère /):

                  /test expr

                  Et je peux voir la même page que celle qui s'affiche quand j'entre la ligne de commande suivante :

                  man --pager='less -p"test expr"' bash

                  Si vous n'aviez entré que le mot test comme motif de recherche, vous auriez pu arriver à trouver le "bon" endroit en maintenant appuyée la touche n (ou N pour revenir en arrière).

                  Il faudra échapper certains caractères dans le motif de recherche,
                  comme, par exemple, si vous voulez rechercher la suite de caractères [[

                  /\[\[

          • [^] # Re: Maintenant qu'on est vendredi...

            Posté par  . Évalué à 4 (+1/-0).

            Et [[ est une builtin du shell,

            [[ est un mot-clé du shell. En Bash du moins, je ne crois pas que ça existe en shell POSIX. [ est bien une « commande interne », aka builtin.

            $ command -V [[
            [[ est un mot-clé du shell

            la commande compgen -k (un builtin) donne la liste des mots-clés, et compgen -b celle des builtins.

            Par ailleurs j’ai découvert que ]] dispensait d’utiliser le ; pour indiquer la fin d’une commande :

            $ if [[ 0 -eq  0 ]]; then echo plop; fi
            plop
            $ if [[ 0 -eq  0 ]] then echo plop; fi
            plop

            Pour ma part je continue à le mettre parce que la coloration syntaxique dans l’éditeur n’a pas l’air d’être au courant ! Puis faut avouer que c’est pénible pour elle ce genre de « facilité » syntaxique.

            • [^] # Re: Maintenant qu'on est vendredi...

              Posté par  . Évalué à 4 (+1/-0).

              Je précise qu’à ce que je sais, [ est à proscrire, sauf à devoir faire du shell strictement conforme à POSIX. [[ le remplace toujours avantageusement. C’est un mot-clé et son comportement est mieux défini, avec moins de « recoins » dangereux.

              • [^] # Re: Maintenant qu'on est vendredi...

                Posté par  (site web personnel, Mastodon) . Évalué à 2 (+0/-0).

                C’est en lien avec ton commentaire précédent : « [ » seul est une commande POSIX qui peut optionnellement être interne ; tandis que « [[ » est une extension interne introduite par Jo…

                “It is seldom that liberty of any kind is lost all at once.” ― David Hume

        • [^] # Re: Maintenant qu'on est vendredi...

          Posté par  . Évalué à 5 (+2/-0). Dernière modification le 27 février 2025 à 19:54.

          C'est amusant que bash ne sache pas s'en sortir sans les espaces. C'est un comportement plutôt rare dans les langages de programmation.

          Disons surtout que c’est ainsi qu’est conçu le langage, qui n’est d’ailleurs pas initialement conçu comme un langage de programmation en tant que tel, même si on peut dire que s’en est un, du fait d’être « Turing-complet ». Accessoirement le langage SQL l’est aussi, et donc un langage de programmation d’après cette définition (pour les implémentations/standards les plus récentes).

          Le shell est… un shell ! D’abord conçu pour que l’utilisateurice interagisse avec lea machin⋅e.

          Ton commentaire c’est comme si tu disais : « C’est amusant que Python ne sache pas s’en sortir sans l’indentation ». ^^

        • [^] # Re: Maintenant qu'on est vendredi...

          Posté par  (site web personnel, Mastodon) . Évalué à 3 (+1/-0).

          Les blancs (donc l’espace dans ton cas) servent à délimiter les tokens ; donc dans le premier cas le shell voit la séquence « [[, $a, -lt, 10, ]] » (qui est OK) et dans le second cas il voit plutôt « [[$a, -lt, 10]] » (où, pour commencer, la commande « [[$a » n’est pas pas trouvée… bon, ici, je suppose que ça commence par « [ » il ne cherche même pas la commande et te dit qu’il y a certainement une erreur de syntaxe) ;-)

          “It is seldom that liberty of any kind is lost all at once.” ― David Hume

Envoyer un commentaire

Suivre le flux des commentaires

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