diff --git a/requests_html.py b/requests_html.py index 94a5f22..042adad 100644 --- a/requests_html.py +++ b/requests_html.py @@ -681,6 +681,8 @@ class HTMLSession(BaseSession): def browser(self): if not hasattr(self, "_browser"): self.loop = asyncio.get_event_loop() + if self.loop.is_running(): + raise RuntimeError("Cannot use HTMLSession within an existing event loop. Use AsyncHTMLSession instead.") self._browser = self.loop.run_until_complete(super().browser) return self._browser @@ -711,3 +713,9 @@ class AsyncHTMLSession(BaseSession): """ Partial original request func and run it in a thread. """ func = partial(super().request, *args, **kwargs) return self.loop.run_in_executor(self.thread_pool, func) + + async def close(self): + """ If a browser was created close it first. """ + if hasattr(self, "_browser"): + await self._browser.close() + super().close() diff --git a/tests/test_requests_html.py b/tests/test_requests_html.py index 129bd5e..5d583dd 100644 --- a/tests/test_requests_html.py +++ b/tests/test_requests_html.py @@ -247,6 +247,15 @@ def test_browser_session(): # assert count_chromium_process() == 0 +@pytest.mark.ok +@pytest.mark.asyncio +async def test_browser_session_fail(): + """ HTMLSession.browser should not be call within an existing event loop> """ + session = HTMLSession() + with pytest.raises(RuntimeError): + session.browser + + @pytest.mark.ok def test_browser_process(): for _ in range(3): @@ -256,6 +265,14 @@ def test_browser_process(): assert r.html.page == None +@pytest.mark.ok +@pytest.mark.asyncio +async def test_async_browser_session(): + session = AsyncHTMLSession() + browser = await session.browser + assert isinstance(browser, Browser) + await session.close() + if __name__ == '__main__': test_containing()