nested “async with” using aiohttp











up vote
0
down vote

favorite












I would like to create a scheduler class that uses aiohttp to make API calls. I tried this:



import asyncio
import aiohttp

class MySession:
def __init__(self):
self.session = None

async def __aenter__(self):
async with aiohttp.ClientSession() as session:
self.session = session
return self

async def __aexit__(self, exc_type, exc_val, exc_tb):
if self.session:
await self.session.close()

async def method1():
async with MySession() as s:
async with s.session.get("https://www.google.com") as resp:
if resp.status == 200:
print("successful call!")

loop = asyncio.get_event_loop()
loop.run_until_complete(method1())
loop.close()


but this just results in an error: RuntimeError: Session is closed. A second approach for the __aenter__ function:



    async def __aenter__(self):
self.session = aiohttp.ClientSession()
return self


works well. Is this a good construct? It doesn't adhere to examples of how to use aiohttp. Also wondering why the first approach isn't working?










share|improve this question


























    up vote
    0
    down vote

    favorite












    I would like to create a scheduler class that uses aiohttp to make API calls. I tried this:



    import asyncio
    import aiohttp

    class MySession:
    def __init__(self):
    self.session = None

    async def __aenter__(self):
    async with aiohttp.ClientSession() as session:
    self.session = session
    return self

    async def __aexit__(self, exc_type, exc_val, exc_tb):
    if self.session:
    await self.session.close()

    async def method1():
    async with MySession() as s:
    async with s.session.get("https://www.google.com") as resp:
    if resp.status == 200:
    print("successful call!")

    loop = asyncio.get_event_loop()
    loop.run_until_complete(method1())
    loop.close()


    but this just results in an error: RuntimeError: Session is closed. A second approach for the __aenter__ function:



        async def __aenter__(self):
    self.session = aiohttp.ClientSession()
    return self


    works well. Is this a good construct? It doesn't adhere to examples of how to use aiohttp. Also wondering why the first approach isn't working?










    share|improve this question
























      up vote
      0
      down vote

      favorite









      up vote
      0
      down vote

      favorite











      I would like to create a scheduler class that uses aiohttp to make API calls. I tried this:



      import asyncio
      import aiohttp

      class MySession:
      def __init__(self):
      self.session = None

      async def __aenter__(self):
      async with aiohttp.ClientSession() as session:
      self.session = session
      return self

      async def __aexit__(self, exc_type, exc_val, exc_tb):
      if self.session:
      await self.session.close()

      async def method1():
      async with MySession() as s:
      async with s.session.get("https://www.google.com") as resp:
      if resp.status == 200:
      print("successful call!")

      loop = asyncio.get_event_loop()
      loop.run_until_complete(method1())
      loop.close()


      but this just results in an error: RuntimeError: Session is closed. A second approach for the __aenter__ function:



          async def __aenter__(self):
      self.session = aiohttp.ClientSession()
      return self


      works well. Is this a good construct? It doesn't adhere to examples of how to use aiohttp. Also wondering why the first approach isn't working?










      share|improve this question













      I would like to create a scheduler class that uses aiohttp to make API calls. I tried this:



      import asyncio
      import aiohttp

      class MySession:
      def __init__(self):
      self.session = None

      async def __aenter__(self):
      async with aiohttp.ClientSession() as session:
      self.session = session
      return self

      async def __aexit__(self, exc_type, exc_val, exc_tb):
      if self.session:
      await self.session.close()

      async def method1():
      async with MySession() as s:
      async with s.session.get("https://www.google.com") as resp:
      if resp.status == 200:
      print("successful call!")

      loop = asyncio.get_event_loop()
      loop.run_until_complete(method1())
      loop.close()


      but this just results in an error: RuntimeError: Session is closed. A second approach for the __aenter__ function:



          async def __aenter__(self):
      self.session = aiohttp.ClientSession()
      return self


      works well. Is this a good construct? It doesn't adhere to examples of how to use aiohttp. Also wondering why the first approach isn't working?







      python python-asyncio aiohttp






      share|improve this question













      share|improve this question











      share|improve this question




      share|improve this question










      asked Nov 9 at 15:16









      user2416984

      1611111




      1611111
























          1 Answer
          1






          active

          oldest

          votes

















          up vote
          3
          down vote













          You can't use with inside a function and have the context manager remain open, no. The with with aiohttp.ClientSession() as session: block exits as soon as you use return to exit the __aenter__ coroutine!



          For the specific case, entering a aiohttp.ClientSession() context manager does nothing but return self. So for that type, just creating the instance and storing it in self.session, and awaiting on self.session.close() suffices here, yes.



          The general pattern for a nested asynchronous context manager is to await the __aenter__ and __aexit__ methods of a nested async context manager from your own such methods (and perhaps pass along the exception information):



          class MySession:
          def __init__(self):
          self.session = None

          async def __aenter__(self):
          self.session = aiohttp.ClientSession()
          await self.session.__aenter__()
          return self

          async def __aexit__(self, exc_type, exc_val, exc_tb):
          if self.session:
          return await self.session.__aexit__(exc_type, exc_val, exc_tb)


          Technically speaking, you should first assure that there is an actual __aexit__ attribute before entering a nested context manager:



          class MySession:
          def __init__(self):
          self.session = None
          self._session_aexit = None

          async def __aenter__(self):
          self.session = aiohttp.ClientSession()
          self._session_aexit = type(self.session).__aexit__
          await self.session.__aenter__()
          return self

          async def __aexit__(self, exc_type, exc_val, exc_tb):
          if self.session:
          return await self._session_aexit.__aexit__(
          self.session, exc_type, exc_val, exc_tb)


          See the official PEP that added the concept.






          share|improve this answer























            Your Answer






            StackExchange.ifUsing("editor", function () {
            StackExchange.using("externalEditor", function () {
            StackExchange.using("snippets", function () {
            StackExchange.snippets.init();
            });
            });
            }, "code-snippets");

            StackExchange.ready(function() {
            var channelOptions = {
            tags: "".split(" "),
            id: "1"
            };
            initTagRenderer("".split(" "), "".split(" "), channelOptions);

            StackExchange.using("externalEditor", function() {
            // Have to fire editor after snippets, if snippets enabled
            if (StackExchange.settings.snippets.snippetsEnabled) {
            StackExchange.using("snippets", function() {
            createEditor();
            });
            }
            else {
            createEditor();
            }
            });

            function createEditor() {
            StackExchange.prepareEditor({
            heartbeatType: 'answer',
            convertImagesToLinks: true,
            noModals: true,
            showLowRepImageUploadWarning: true,
            reputationToPostImages: 10,
            bindNavPrevention: true,
            postfix: "",
            imageUploader: {
            brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
            contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
            allowUrls: true
            },
            onDemand: true,
            discardSelector: ".discard-answer"
            ,immediatelyShowMarkdownHelp:true
            });


            }
            });














             

            draft saved


            draft discarded


















            StackExchange.ready(
            function () {
            StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53228434%2fnested-async-with-using-aiohttp%23new-answer', 'question_page');
            }
            );

            Post as a guest















            Required, but never shown

























            1 Answer
            1






            active

            oldest

            votes








            1 Answer
            1






            active

            oldest

            votes









            active

            oldest

            votes






            active

            oldest

            votes








            up vote
            3
            down vote













            You can't use with inside a function and have the context manager remain open, no. The with with aiohttp.ClientSession() as session: block exits as soon as you use return to exit the __aenter__ coroutine!



            For the specific case, entering a aiohttp.ClientSession() context manager does nothing but return self. So for that type, just creating the instance and storing it in self.session, and awaiting on self.session.close() suffices here, yes.



            The general pattern for a nested asynchronous context manager is to await the __aenter__ and __aexit__ methods of a nested async context manager from your own such methods (and perhaps pass along the exception information):



            class MySession:
            def __init__(self):
            self.session = None

            async def __aenter__(self):
            self.session = aiohttp.ClientSession()
            await self.session.__aenter__()
            return self

            async def __aexit__(self, exc_type, exc_val, exc_tb):
            if self.session:
            return await self.session.__aexit__(exc_type, exc_val, exc_tb)


            Technically speaking, you should first assure that there is an actual __aexit__ attribute before entering a nested context manager:



            class MySession:
            def __init__(self):
            self.session = None
            self._session_aexit = None

            async def __aenter__(self):
            self.session = aiohttp.ClientSession()
            self._session_aexit = type(self.session).__aexit__
            await self.session.__aenter__()
            return self

            async def __aexit__(self, exc_type, exc_val, exc_tb):
            if self.session:
            return await self._session_aexit.__aexit__(
            self.session, exc_type, exc_val, exc_tb)


            See the official PEP that added the concept.






            share|improve this answer



























              up vote
              3
              down vote













              You can't use with inside a function and have the context manager remain open, no. The with with aiohttp.ClientSession() as session: block exits as soon as you use return to exit the __aenter__ coroutine!



              For the specific case, entering a aiohttp.ClientSession() context manager does nothing but return self. So for that type, just creating the instance and storing it in self.session, and awaiting on self.session.close() suffices here, yes.



              The general pattern for a nested asynchronous context manager is to await the __aenter__ and __aexit__ methods of a nested async context manager from your own such methods (and perhaps pass along the exception information):



              class MySession:
              def __init__(self):
              self.session = None

              async def __aenter__(self):
              self.session = aiohttp.ClientSession()
              await self.session.__aenter__()
              return self

              async def __aexit__(self, exc_type, exc_val, exc_tb):
              if self.session:
              return await self.session.__aexit__(exc_type, exc_val, exc_tb)


              Technically speaking, you should first assure that there is an actual __aexit__ attribute before entering a nested context manager:



              class MySession:
              def __init__(self):
              self.session = None
              self._session_aexit = None

              async def __aenter__(self):
              self.session = aiohttp.ClientSession()
              self._session_aexit = type(self.session).__aexit__
              await self.session.__aenter__()
              return self

              async def __aexit__(self, exc_type, exc_val, exc_tb):
              if self.session:
              return await self._session_aexit.__aexit__(
              self.session, exc_type, exc_val, exc_tb)


              See the official PEP that added the concept.






              share|improve this answer

























                up vote
                3
                down vote










                up vote
                3
                down vote









                You can't use with inside a function and have the context manager remain open, no. The with with aiohttp.ClientSession() as session: block exits as soon as you use return to exit the __aenter__ coroutine!



                For the specific case, entering a aiohttp.ClientSession() context manager does nothing but return self. So for that type, just creating the instance and storing it in self.session, and awaiting on self.session.close() suffices here, yes.



                The general pattern for a nested asynchronous context manager is to await the __aenter__ and __aexit__ methods of a nested async context manager from your own such methods (and perhaps pass along the exception information):



                class MySession:
                def __init__(self):
                self.session = None

                async def __aenter__(self):
                self.session = aiohttp.ClientSession()
                await self.session.__aenter__()
                return self

                async def __aexit__(self, exc_type, exc_val, exc_tb):
                if self.session:
                return await self.session.__aexit__(exc_type, exc_val, exc_tb)


                Technically speaking, you should first assure that there is an actual __aexit__ attribute before entering a nested context manager:



                class MySession:
                def __init__(self):
                self.session = None
                self._session_aexit = None

                async def __aenter__(self):
                self.session = aiohttp.ClientSession()
                self._session_aexit = type(self.session).__aexit__
                await self.session.__aenter__()
                return self

                async def __aexit__(self, exc_type, exc_val, exc_tb):
                if self.session:
                return await self._session_aexit.__aexit__(
                self.session, exc_type, exc_val, exc_tb)


                See the official PEP that added the concept.






                share|improve this answer














                You can't use with inside a function and have the context manager remain open, no. The with with aiohttp.ClientSession() as session: block exits as soon as you use return to exit the __aenter__ coroutine!



                For the specific case, entering a aiohttp.ClientSession() context manager does nothing but return self. So for that type, just creating the instance and storing it in self.session, and awaiting on self.session.close() suffices here, yes.



                The general pattern for a nested asynchronous context manager is to await the __aenter__ and __aexit__ methods of a nested async context manager from your own such methods (and perhaps pass along the exception information):



                class MySession:
                def __init__(self):
                self.session = None

                async def __aenter__(self):
                self.session = aiohttp.ClientSession()
                await self.session.__aenter__()
                return self

                async def __aexit__(self, exc_type, exc_val, exc_tb):
                if self.session:
                return await self.session.__aexit__(exc_type, exc_val, exc_tb)


                Technically speaking, you should first assure that there is an actual __aexit__ attribute before entering a nested context manager:



                class MySession:
                def __init__(self):
                self.session = None
                self._session_aexit = None

                async def __aenter__(self):
                self.session = aiohttp.ClientSession()
                self._session_aexit = type(self.session).__aexit__
                await self.session.__aenter__()
                return self

                async def __aexit__(self, exc_type, exc_val, exc_tb):
                if self.session:
                return await self._session_aexit.__aexit__(
                self.session, exc_type, exc_val, exc_tb)


                See the official PEP that added the concept.







                share|improve this answer














                share|improve this answer



                share|improve this answer








                edited Nov 9 at 15:25

























                answered Nov 9 at 15:19









                Martijn Pieters

                692k12923972236




                692k12923972236






























                     

                    draft saved


                    draft discarded



















































                     


                    draft saved


                    draft discarded














                    StackExchange.ready(
                    function () {
                    StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53228434%2fnested-async-with-using-aiohttp%23new-answer', 'question_page');
                    }
                    );

                    Post as a guest















                    Required, but never shown





















































                    Required, but never shown














                    Required, but never shown












                    Required, but never shown







                    Required, but never shown

































                    Required, but never shown














                    Required, but never shown












                    Required, but never shown







                    Required, but never shown







                    Popular posts from this blog

                    how to define a CAPL function taking a sysvar argument

                    Schultheiß

                    Extract exact text in tags