title: Python websockets lib client persistent connection (with class implementation)
body: <p>I'm trying to implement a websocket client in python using <code>websockets</code> and the apparently mandatory <code>asyncio</code> which I never used before (and I have a hard time to understand...).</p>
  
  <p>I've read a lot on the subject and saw (too) many examples here and everywhere, but I can't find a way to properly make a websocket client with a persistent connection.</p>
  
  <ul>
  <li>I need to have a persistent connection because the commands need to be requested on the same connection, the first one being an authentication command.</li>
  <li>The remote server is a 3rd party API I don't have any control over.</li>
  <li>I suppose I could run an authentication request along with each command my program sends but that does not feel right to open > auth > request > close for each command instead of keeping one connection alive during the whole program's life</li>
  <li>My implementation is a library using many classes and I need to wrap the websocket connector/handler in one of them</li>
  </ul>
  
  <p>Here's what I have right now, based on examples I found here and there (with some obfuscated data) :</p>
  
  <pre class="lang-py prettyprint-override"><code>import json
  import asyncio
  from websockets import connect
  
  
  URL = 'wss://server.com/endpoint'
  
  
  class Websocket:
      async def __aenter__(self):
          self._conn = connect(URL)
          self.websocket = await self._conn.__aenter__()
          return self
  
      async def __aexit__(self, *args, **kwargs):
          await self._conn.__aexit__(*args, **kwargs)
  
      async def send(self, message):
          await self.websocket.send(message)
  
      async def receive(self):
          return await self.websocket.recv()
  
  
  class Handler:
      def __init__(self):
          self.wws = Websocket()
          self.loop = asyncio.get_event_loop()
  
      def command(self, cmd):
          return self.loop.run_until_complete(self.__async__command(cmd))
  
      async def __async__command(self, cmd):
          async with self.wws as echo:
              await echo.send(json.dumps(cmd))
              return await echo.receive()
  
  
  def main():
      handler = Handler()
  
      foo = handler.command('authentication command')
      print('auth: ', foo)
  
      bar = handler.command('another command to run depending on the first authentication')
      print('command: ', bar)
  
  
  if __name__ == '__main__':
      main()
  
  </code></pre>
  
  <p>Basically right now I get these answers (simplified and obfuscated) :</p>
  
  <pre class="lang-none prettyprint-override"><code>auth: Ok, authenticated
  command: Command refused, not authenticated
  </code></pre>
  
  <p>I suppose my problem is that the block <code>async with self.wws as echo:</code> kind of create the connection, runs its code then drop it instead of keeping the connection alive. Since we are not using a usual <code>__init__</code> here but some <code>asyncio</code> voodoo I don't understand, I'm kind of stuck.</p>