8
votes

Est-il possible d'appeler EXED afin qu'il soit compatible avec Python 3 et Python 2?

J'utilise l'instruction EXEC dans certains CODE PYTHON 2, et j'essaie de rendre ce code compatible avec Python 2 et Python 3, mais dans Python 3, EXEC a changé d'une instruction dans une fonction. Est-il possible d'écrire du code compatible avec Python 2 et 3? J'ai lu sur Python 2 et Python 3 Dual Development , mais je suis intéressé par des solutions spécifiques au Exec Énoncé / Modifications de la fonction.

Je réalise que EXEC est généralement découragé, mais je construisais un plug-in Eclipse qui implémente le codage en direct au-dessus de PYDEV. Voir le Page du projet pour plus de détails.


3 commentaires

Lire le livre: Python3porting.com/Difforences.html#exec


@Lennartregebro Cette source est erronée sur exec


Hein, je suis sûr que j'ai essayé ça. Va essayer à nouveau.


3 Réponses :


6
votes

J'ai trouvé plusieurs options pour ce faire, avant de poster Antti Publié sa réponse que Python 2 prend en charge le python 3 Syntaxe de fonction Exec .

La première expression peut également être un tuple de longueur 2 ou 3. Dans ce cas, les pièces en option doivent être omises. Le formulaire EXEC (Expr, globaux) est équivalent à Exec Expr dans les globaux , tandis que le formulaire EXEC (Expr, globaux, locaux) est équivalent EXEC Expr dans les globaux locaux . La forme tuple de EXED fournit une compatibilité avec Python 3, où EXED est une fonction plutôt qu'une déclaration.

Si vous ne voulez pas l'utiliser pour une raison quelconque, voici toutes les autres options que j'ai trouvées.

Stubs d'importation < P> Vous pouvez déclarer deux talons d'importation différents et importer selon l'interprète actuel. Ceci est basé sur ce que j'ai vu dans le code source Pydev.

Voici ce que vous mettez dans le module principal: xxx

Voici ce que vous mettez dans < Code> exécu_python2.py : xxx

voici ce que vous mettez en exécu_python3.py : xxx < / PRE>

EXEC dans EVAL

NED BATCHELDER Posté une technique qui enveloppe l'instruction EXEC dans un appel à eval de sorte qu'il ne provoquera pas d'erreur de syntaxe dans Python 3. C'est intelligent, mais pas clair. xxx

six package

Six package est une bibliothèque de compatibilité pour la rédaction de code qui fonctionnera sous Python 2 et Python 3. Il a un exécuté _ () fonction qui se traduit par les deux versions. Je ne l'ai pas essayé.


4 commentaires

Six est génial, vous devriez lui donner un coup. Fabriqué le Python 3 portant je faisais beaucoup plus facilement, et beaucoup moins de hacky (je vous regarde, "EXEC dans EVAL").


J'étais un peu hésitant à ajouter une dépendance du projet, @delnan. Incluez-vous simplement des fichiers supplémentaires dans votre projet ou une personne qui utilise votre projet doit-elle installer six aussi?


Dans mon cas, j'ai porté un outil de construction qui se démarque pour l'installation, de sorte que les dépendances étaient difficiles (bien qu'il n'y en ait, ils ne sont tout simplement pas nécessaires lors de la botte), en particulier avec six. J'ai donc fini par le regrouper en tant que sous-module, qui est autorisé et était trivial à l'exception de six.MOVES (nécessite un changement d'une ligne, mais je n'ai pas encore besoin de changer. ). Vous pouvez voir les changements dans leur intégralité à github.com/paver/paver/pull/82 (N'ayez pas peur par le grand nombre de changements, 90% de celle résultant d'un script de bootstrap Virtualenv et de supprimer et d'ajouter des bibliothèques groupées).


@Donkirkby: Vous pouvez soit déclarer six une dépendance à setup.py, ce qui signifie que toute personne qui installe votre module obtiendra automatiquement six installées (en supposant qu'ils utilisent easy_install ou PIP ou Buildout, et ils doivent). Ou vous pouvez simplement mettre le fichier SIX.PY dans votre module.



13
votes

Certaines Guides de portage Python Obtenez le EXEC code> mal fort>:

Si vous devez transmettre les dictionnaires globaux ou locaux, vous devrez définir une fonction personnalisée avec deux implémentations différentes, une pour Python 2 et une pour Python 3. Comme d'habitude six code> comprend un excellent Mise en œuvre de cet appelé exec _ () code>. p> BlockQuote>

aucune fonction personnalisée n'est nécessaire pour porter le code Python 2 dans Python 3 Strong> (*). Vous pouvez faire exécu (code) code>, exécuté (code, globs) code> et exécuté (code, globs, locs) code> dans python 2, et il travaux. P>

Python a TOUJOURS STRY> PYTHON 3 accepté Python 3 compatible "Syntaxe" pour EXEC code> pour aussi longtemps que exec code> existait. La raison en est que Python 2 et Python 1 (?!) Avoir un piratage pour rester compatible à l'envers em> avec Python 0.9.8 dans lequel exécuté code> était une fonction. Maintenant, si EXEC code> est transmis un 2 tuple, il est interprété comme (code, globaux) code> et dans le cas d'un 3 tuple, il est interprété comme (Code, globals, locaux) code>. Oui, le exec _ code > dans six code> est inutilement compliqué. p>

Ainsi, p> xxx pré>

est garanti de fonctionner de la même manière dans CPPHON 0.9.9, 1.x, 2.x, 3.x; et j'ai également vérifié que cela fonctionne dans Jython 2.5.2, PYPY 2.3.1 (Python 2.7.6) et IronPython 2.6.1: P>

def print_arg(arg):
    def do_print():
        print(arg)

    eval(compile('do_print(); print("it really works")', '<string>', 'exec'))


5 commentaires

Ce n'est pas vrai si EXEC est dans une fonction. Vous obtenez SyntaxError: Unqualified Exec n'est pas autorisé dans la fonction "Whatevs" contient une fonction imbriquée avec des variables libres


@Hounshell j'ai ajouté une responsabilité de non-responsabilité. Cependant, la version originale de ma réponse indique que "aucune fonction personnalisée de ce type n'est nécessaire pour le port Python 2 Code dans Python 3". Ce code n'a pas fonctionné à Python 2 pour commencer; et a besoin d'une enveloppe dans Python 2 de toute façon.


Mais ne serait pas exec 'imprimer "a" "in {}, {} réussir dans cette situation à Python 2? EXEC ('Imprimer "A"', {}, {}) jette la même exception.


Je reçois des résultats différents sur différentes machines. Je ne sais pas si c'est due à la version OS ou Python. Pastebin.com/xgcjf8mt TL; DR: Ubuntu 14.04 avec Python 2.7.6 jette une erreur, OSX 10.11.6 avec Python 2.7.10 ne le fait pas.


Mais ce n'est pas double conformément à Python3. SyntaxError: Syntaxe non valide Je pense que la seule façon de faire quelque chose qui est conforme aux trois (<2.7.9,> = 2.7.9,> 3.0) est d'utiliser eval . J'ai essayé ma main à cela dans une réponse séparée.



1
votes

J'avais besoin de le faire, je ne pouvais pas utiliser six, et ma version de Python ne prend pas en charge la méthode de @ Antti, car je l'ai utilisé dans une fonction imbriquée avec des variables libres. Je ne voulais pas non plus d'importations inutiles. Voici ce que je suis venu avec. Cela doit probablement être dans le module, pas dans une méthode: xxx

après, _exec fonctionne comme la version Python3. Vous pouvez soit remettre une chaîne, soit l'exécuter via compile () . Il ne fera pas les globaux ou les locaux que vous voulez probablement, alors passez-les dans: xxx

ou non. Je suis un poteau Stackoverflow, pas un flic.

mises à jour:

Pourquoi n'utilisez-vous pas simplement eval () ? eval () attend un expression , tandis que exécuté () attend déclarations . Si vous venez d'obtenir une expression, cela n'a pas vraiment ce que vous utilisez car toutes les expressions valides sont des déclarations valides, mais l'inverse n'est pas vraie. Il suffit d'exécuter une méthode est une expression, même si cela ne renvoie rien; Il y a un non implicite retourné.

Ceci est démontré en essayant d'évaluer PASS , qui est une instruction: xxx < / pré>


5 commentaires

sauf, bien sûr, vous n'avez pas besoin exécu pour exécuter le code ... Vous pouvez utiliser eval à la place, et ce ne serait pas être soumis à ces erreurs de syntaxe


Mais eval n'autorise pas plusieurs déclarations. Ceci utilise uniquement eval pour terminer le exécuté . C'est toujours exécuté qui exécute le code. Réponse mise à jour pour démontrer un cas où eval échouerait.


Voir ma réponse sur l'utilisation eval .


Je viens d'essayer votre do_print () exemple avec python 2.7 et 3.5. Ils ont tous deux fonctionné correctement avec l'intégré EXEC () et imprimé 7. Pas de spécial _EXEC () nécessaire. Qu'est-ce qui n'a pas fonctionné pour vous?


Antidi l'a adressée ci-dessus. Il y avait un changement de 2.7.9, j'utilisais 2.7.6