-
Notifications
You must be signed in to change notification settings - Fork 1.1k
Description
System info
- Playwright Version: [v1.33.0]
- Operating System: [Windows 11]
- Browser: [Chromium]
- Other info:
Source code
- I provided exact source code that allows reproducing the issue locally.
Link to the GitHub repository with the repro
[https://github.com/your_profile/playwright_issue_title]
or
Test file (self-contained)
import asyncio
from playwright.async_api import async_playwright
import six
from multiprocessing import Lock
class SingletonType(type):
def __new__(mcs, name, bases, attrs):
cls = super(SingletonType, mcs).__new__(mcs, name, bases, attrs)
cls.__shared_instance_lock__ = Lock()
return cls
def __call__(cls, *args, **kwargs):
with cls.__shared_instance_lock__:
try:
return cls.__shared_instance__
except AttributeError:
cls.__shared_instance__ = super(SingletonType, cls).__call__(*args, **kwargs)
return cls.__shared_instance__
import six
@six.add_metaclass(SingletonType)
class PlaywrightBrowserSession:
timeout = 60
browser = None
is_open_url = False
p = None
page = None
def __init__(self, timeout=60) -> None:
self.timeout = timeout
@classmethod
async def with_init_brower(cls, **kwargs):
self = cls(**kwargs)
if self.browser is None:
await self.init_brower()
return self
async def init_brower(self):
self.p = await async_playwright().start()
self.browser = await self.p.chromium.launch_persistent_context(
user_data_dir = "",
headless=False,
timeout = self.timeout*1000,)
async def open_url(self, base_url):
self.page = await self.browser.new_page()
await self.page.goto(base_url)
self.is_open_url = True
base_url = "https://www.baidu.com"
def print_session_info(session):
print("session.browser: ", session.browser)
print("session.page: ", session.page)
print("session.p: ", session.p)
async def test_one_post_something(**kwargs):
session = await PlaywrightBrowserSession.with_init_brower(timeout=30)
print_session_info(session)
if session.is_open_url == False:
print("need_open_url")
await session.open_url(base_url)
await session.page.wait_for_timeout(2*1000)
print_session_info(session)
print("first_post_before")
first_response = await session.page.request.post(f"{base_url}/test.php")
first_result = await first_response.text()
print(first_result)
print("first_post_after")
print("second_post_before")
second_response = await session.page.request.post(f"{base_url}/test.php")
second_result = await second_response.text()
print(second_result)
print("second_post_after")
return "finished"
async def test_post_something(**kwargs):
try:
await test_one_post_something(**kwargs)
except Exception as e:
print(f"error: ", e)
while True:
content = input(">>> ")
asyncio.run(test_post_something(),debug=True)In the code I have created a singleton object to hold the brower, page etc.
The purpose is to be able to quickly post from this page. This ”post” will triggered multiple times.
I'm saving the brower and page for the next quick post so that I don't have to open the browser, open the url, set an extra header, etc.
The first call to test_one_post_something does issue the post command twice, but the second call to test_one_post_something generates an error('NoneType' object has no attribute 'send')
Is this due to the use of the asyncio.run call?
Is this a known behavior and what can I do to avoid this problem?
Steps
- [Run the test]
- input test, you will get it :
>>> test
session.browser: <BrowserContext browser=None>
session.page: None
session.p: <playwright._impl._playwright.Playwright object at 0x0000013F5DBEEBD0>
need_open_url
session.browser: <BrowserContext browser=None>
session.page: <Page url='https://www.baidu.com/'>
session.p: <playwright._impl._playwright.Playwright object at 0x0000013F5DBEEBD0>
first_post_before
<html>
<head>
<title>您访问的页面不存在!</title>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
</head>
<body></body>
</html>
first_post_after
second_post_before
<html>
<head>
<title>您访问的页面不存在!</title>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
</head>
<body></body>
</html>
second_post_after
- input test again, you will get it :
>>> test
session.browser: <BrowserContext browser=None>
session.page: <Page url='https://www.baidu.com/'>
session.p: <playwright._impl._playwright.Playwright object at 0x0000013F5DBEEBD0>
first_post_before
error: 'NoneType' object has no attribute 'send'
Expected
I want both times to return the result of the first input test
Actual
The first time it returned what I expected, but the second time it printed an error.
Based on the printout, I can assume that there is a problem with the state of the page.