2015-05-12 8 views
10

Sto sviluppando il framework di bot per la chat di Python con asyncio. Ma guardo PEP-492 e c'è una nuova sintassi, async/await e finalmente accettato.Coroutine in python tra 3.4 e 3.5, Come posso mantenere la compatibilità di backwords?

Mi piace la sintassi async/await e voglio usarlo. ma mi preoccupo della compatibilità con 3,4 backwords.

Se utilizzo la nuova sintassi nel mio codice, qualcuno può usarlo in 3.4?

Per esempio, ho scrivere del codice in questo modo,

import asyncio 

class ChatBot: 
    def __init__(self, loop): 
     self.loop = loop 

    async def connect(self): 
     self.reader, self.writer = await asyncio.open_connect(HOST, PORT, loop=self.loop) 

    async def read(): 
     return await self.reader.read() 

    async def run(self): 
     running = True 
     while running: 
      try: 
       await self.connect() 
       line = await self.read() 
       if not line: 
        continue 
       await self.parse(line) 
      except BotInternalError as e: 
       if e.stop: 
        running = False 
        break 
      except: 
       pass 

    async def parse(self, msg): 
     if msg.startswith('PING'): 
      self.pong() 
     elif msg.startswith('ERROR'): 
      self.error() 
     else: 
      await self.some_work(msg) 

    async def some_work(self, msg): 
     # some looooooooong works 
     self.send(msg) 

    def send(self, msg): 
     self.writer.write(msg) 

Than, posso usarlo con questa fonte in py35

loop = asyncio.get_event_loop() # I don't know it really needed in py35. 
bot = ChatBot(loop) 
asyncio.run_until_complete(bot.run()) 

Ma, py34 non hanno await sintassi. Se ho caricato sopra la fonte su PyPI senza vincoli di versione e qualcuno l'ha installato su py34, funzionerà correttamente? Come posso tenerlo?

risposta

13

Se è necessario supportare Python 3.4 nel codice, è necessario utilizzare la vecchia sintassi di stile @asyncio.coroutine/yield from. Non c'è modo di supportare la sintassi async/await senza eseguire 3.5; Otterrai uno SyntaxError in fase di compilazione alla versione 3.4 o successiva.

L'unica cosa che sfrutta le nuove funzionalità si può fare in modo compatibile con le versioni precedenti è aggiungere i vari __a*__ metodi alle classi se del caso (__aiter__, __aenter__, __aexit__, ecc), utilizzando il yield from sintassi di coroutine. In questo modo, gli oggetti possono supportare le istruzioni async with/async for, in modo che gli utenti della libreria che eseguono Python 3.5 possano sfruttare le nuove funzionalità.

Ad esempio, questa classe può essere utilizzato con async with, ma non si rompe quando viene eseguito su Python 3.4:

import asyncio 

class Test: 
    def __enter__(self): 
     return self 

    def __exit__(self, *args): 
     print("arg") 

    @asyncio.coroutine 
    def __aenter__(self): 
     yield from self.init_state() 
     return self 

    @asyncio.coroutine 
    def init_state(self): 
     yield from asyncio.sleep(2) # Pretend this is real initialization 

    @asyncio.coroutine 
    def __aexit__(self, *args): 
     return self.__exit__(self, *args) 

su Python 3.5:

import asyncio 
from test import Test 

async def main(): 
    print("entering with") 
    async with Test() as t: 
     print("in here") 

loop = asyncio.get_event_loop() 
loop.run_until_complete(main()) 

su Python 3.4

import asyncio 
from test import Test 

@asyncio.coroutine 
def oldmain(): 
    print("entering with") 
    with Test() as t: 
     yield from t.init_state() 
     print("in here") 

loop = asyncio.get_event_loop() 
loop.run_until_complete(oldmain()) 

Questo probabilmente non è utile se si sta scrivendo un'applicazione che utilizza asyncio, ma se stai sviluppando una libreria o un framework destinato ad essere utilizzato da altri sviluppatori, vale la pena farlo.

+6

È divertente vedere la struttura '@ asyncio.coroutine' descritta come" vecchia "quando è apparsa solo nella versione più recente di Python. :-) –

+0

@MarkDickinson Effettivamente. Python si sta evolvendo piuttosto rapidamente in questo spazio. :) – dano

+1

Quindi, poiché la transizione tra Python 2 e Python 3 è stata così semplice, la comunità Python ha deciso di rendere la transizione semplice anche tra Python 3.4 e Python 3.5 :-)? – z1naOK9nu8iY5A

Problemi correlati