2011-12-14 13 views
34

Esistono molti modi per includere in Python 3.x in Python 2.x, in modo che il codice degli script Python 2.x possa essere facilmente convertito in Python 3.x in futuro. Uno di questi esempi è il sostituto di print dichiarazione con print() funzione:Come scrivere Python 2.x quanto più compatibile con Python 3.x possibile?

>>> from __future__ import print_function 

Esiste un elenco o una risorsa che potrebbe dare una qualche idea come fare codice Python 2.x come vicino a Python 3.x possibile?

Potrebbe fornire esempi di altre utili importazioni o definizioni che possono rendere Python 2.x aspetto e si comportano più come Python 3.x?

Supponiamo che abbiamo a disposizione l'ultimo Python 2.x (2.7.2 al momento, credo).

+2

risposte a [questo] (http://stackoverflow.com/questions/5937251/writing-python-2-7-code-that-is-as-close-to-python-3-x-syntax-as -possibile) la domanda può aiutare. –

+2

@BoraCaglayan: Sì, il titolo è quasi identico a quello di questa domanda :) Ma sfortunatamente quel collegamento riguarda le app Django (ovvero esiste una base di codice esistente e non devi rovinare l'app). La mia domanda riguarda app appena create, in cui non è necessario preoccuparsi che ad es. c'è molto codice che usa l'istruzione 'print' invece della funzione. Questo elimina molti problemi, credo. – Tadeck

+0

@Tadeck: No, la funzione di stampa è un problema molto banale.La maggior parte dei problemi è la stessa, e molto più difficile. Non si evita realmente alcuna difficoltà di compatibilità usando Django. –

risposta

22

sto dando gli ultimi ritocchi su una linea di circa 5000, la deduplicazione programma di backup (http://stromberg.dnsalias.org/~strombrg/backshift/) che gira su CPython 2. [ 567], CPython 3. [0123] (3.3 è ancora alpha 0), Pypy 1.7 e trunk Jython. Ho anche provato IronPython, ma era una cosa abbastanza diversa - non aveva una libreria standard, quindi nessun amore backshift. Oh, e può usare Cython per il suo ciclo più interno, o psyco - ma Pypy è più veloce di entrambi, specialmente sui sistemi a 32 bit.

In ogni caso, ho scoperto che a scrivere codice che viene eseguito altrettanto bene su 2.xe 3.x tutto quello che dovevo fare era:

1) (variabile) funziona allo stesso modo su entrambi 2.xe 3.x. print (variabile1, variabile2) no. Per 2.x, print (variabile) dice "valuta questa espressione tra parentesi e stampa il singolo risultato usando l'istruzione print". Per 3.x, print (variabile) dice "chiama la funzione di stampa su questo singolo risultato. Quindi print ('abc% d% d'% (1, 2)) funziona bene in entrambi, perché è un risultato a valore singolo, ed entrambi GROK l'operatore% per la formattazione stringa.

2) Evitare costanti ottali. Invece di scrivere 0755, scrivere (7 * 64 + 5 * 8 + 5).

3) per fare I/O binario in entrambi, ho usato il mio modulo bufsock: http://stromberg.dnsalias.org/~strombrg/bufsock.html Mi piacerebbe aprire un file e avvolgerlo con bufsock (o usare la classe rawio nel modulo). 2.x, restituirebbe una stringa di byte codificata come 8 stringhe di caratteri bit. In 3.x, questo restituirebbe un oggetto byte, che agisce in modo simile a un elenco di interi piccoli, quindi passerei l'uno o l'altro, testando con "isinstance (foo, str)" secondo necessità distinguere tra i due d questo, perché per un programma di backup, i byte sono byte - non volevo fare scherzi con le codifiche che ostacolavano il salvataggio dei dati in modo affidabile, e non tutte le codifiche andavano bene.

4) Quando si eseguono eccezioni, evitare la parola chiave "as". Invece, utilizzare EG:

try: 
    self.update_timestamp() 
    except (OSError, IOError): 
    dummy, utime_extra, dummy = sys.exc_info() 
    if utime_extra.errno == errno.ENOENT: 

5) Un gruppo di moduli è stato rinominato nella transizione da 2.x a 3.x.Quindi provare l'importazione di uno dei due in un modulo altrimenti vuoto, con qualcosa come:

try: 
    from anydbm import * 
except ImportError: 
    from dbm import * 

... questo apparirebbe in un modulo di per sé, con un nome EG adbm.py. Quindi ogni volta che mi serviva un negozio con valore-chiave, importavo adbm invece delle due cose diverse necessarie per 2.xo 3.x direttamente. Poi avrei filtrato tutto tranne quel modulo tozzo, adbm.py - e cose del genere a cui il difensore non piaceva. L'idea era di pylint tutto il possibile, con le eccezioni alla regola "tutto ciò che è necessario pylint" in un piccolo modulo tutto da solo, un'eccezione per modulo.

6) Aiuta molto a configurare test di unità e test di sistema automatici eseguiti su 2.xe 3.xe quindi esegue frequentemente test su almeno un interprete 2.x e almeno un 3. x interprete. Eseguo spesso anche il mio codice sul mio codice, anche se solo un problema che ha verificato la conformità 2.5.x - Ho iniziato il progetto prima che pylint avesse il supporto 3.x.

7) Ho messo su un piccolo modulo "python2x3", che ha un paio di costanti e callable per rendere la vita più facile: http://stromberg.dnsalias.org/svn/python2x3/trunk/python2x3.py

8) b '' letterali non funzionano in 2.5, anche se specie di lavoro in 2. [67]. Invece di provare a eseguire il preprocesso o qualcosa del genere, ho impostato un constants_mod.py che aveva un sacco di cose che normalmente sarebbero b "letterali in 3.x, e li ho convertiti da una semplice stringa a qualsiasi tipo di" byte "è per 2 .xo 3.x. Quindi vengono convertiti una volta sull'importazione del modulo, non più e più a runtime. Se hai scelto come target 2. [67] e su, c'è forse un modo migliore, ma quando ho iniziato il progetto Pypy era compatibile solo con 2.5, e Jython lo è ancora.

9) In 2.x, gli interi lunghi hanno un suffisso L. In 3.x, tutti gli interi sono lunghi. Quindi sono andato solo evitando le lunghe costanti intere il più possibile; 2.x promuoverà un intero per il tempo necessario, quindi sembra che funzioni per la maggior parte delle cose.

10) Aiuta MOLTO ad avere un sacco di interpreti Python in giro per testare. Ho costruito 2. [567] e 3. [0123] e li ho messi in /usr/local/cpython-x.y/ per un facile test. Ho anche messo alcuni Pypy e Jython in/usr/local, ancora per un facile test. Avere uno script per automatizzare le build di CPython era piuttosto prezioso.

Credo che queste fossero tutte le contorsioni necessarie per ottenere un codebase Python altamente portatile in un progetto non banale. L'unica grande omissione nella lista che ho scritto sopra è che non sto cercando di usare oggetti unicode - è qualcos'altro qualcun altro è probabilmente meglio qualificato per commentare.

HTH

+1

ehi, sai che il trucco sys.exc_info() farà piangere Pypy? – fijal

+0

No, non lo ero. Grazie per averlo menzionato. Cosa è necessario per risolvere il problema in Pypy? – dstromberg

+0

Lo fa davvero? Questo sembra funzionare: >>>> provare: .... manichino = 1/0 .... tranne: .... manichino, foo, manichino = sys.exc_info() ... stampa foo .... divisione intera di zero >>>> – dstromberg

7

Si consiglia di verificare Porting Python Code to 3.0. Sebbene sia finalizzato al porting, risponde essenzialmente alla stessa domanda; semplicemente non andrai fino in fondo.

+0

Grazie. Sono particolarmente interessato alla seconda opzione dal link che hai fornito: "_make codice eseguito non modificato in entrambi Python 2 e Python 3_". Questa opzione è la più vicina a ciò che sto cercando di ottenere. – Tadeck

1

ho questo in cima alla mia Python template 2.7 script:

from __future__ import division, print_function 
from future_builtins import ascii, filter, hex, map, oct, zip 
+2

Questo è abbastanza vicino per l'uso pratico. E future_builtins non esiste in Python 3, quindi questo codice non verrà eseguito su Python 3. –

+1

Non sarebbe più pratico mantenere il modulo furure_builtins nella libreria standard Python 3, in modo da rendere più semplice il supporto sia Versione Python2 e Python3 da una base di codice comune? – pmav99

7

C'è a whole chapter su questo in "Porting to Python 3". Inoltre, non perdere le appendici, che elencano le differenze linguistiche con soluzioni alternative per supportare entrambe le lingue.

Probabilmente vorrete usare lo six library, anche se è possibile farlo senza di esso.

1

Poiché non è stato ancora menzionato: ho trovato questo cheat sheet per essere veramente utile per questo scopo esatto.

Problemi correlati