@@ -80,24 +80,30 @@ def __init__(
80
80
81
81
self ._context_creation_lock : Lock | None = None
82
82
83
-
84
83
async def _get_context_creation_lock (self ) -> Lock :
85
- """Context checking and creation should be done with lock to prevent multiple attempts to create context."""
84
+ """Get context checking and creation lock.
85
+
86
+ It should be done with lock to prevent multiple concurrent attempts to create context, which could lead to
87
+ memory leak as one of the two concurrently created contexts will become orphaned and not properly closed.
88
+ """
86
89
if self ._context_creation_lock :
87
90
return self ._context_creation_lock
88
- self ._context_creation_lock = Lock ()
91
+ self ._context_creation_lock = Lock ()
89
92
return self ._context_creation_lock
90
93
91
- async def _ensure_browser_context (self ,
92
- browser_new_context_options : Mapping [str , Any ] | None = None ,
93
- proxy_info : ProxyInfo | None = None ,
94
- ) -> None :
94
+ async def _get_browser_context (
95
+ self ,
96
+ browser_new_context_options : Mapping [str , Any ] | None = None ,
97
+ proxy_info : ProxyInfo | None = None ,
98
+ ) -> BrowserContext :
99
+ """Ensure that the browser context is set."""
95
100
async with await self ._get_context_creation_lock ():
96
101
if not self ._browser_context :
97
102
self ._browser_context = await self ._create_browser_context (
98
103
browser_new_context_options = browser_new_context_options ,
99
104
proxy_info = proxy_info ,
100
105
)
106
+ return self ._browser_context
101
107
102
108
@property
103
109
@override
@@ -170,8 +176,8 @@ async def new_page(
170
176
)
171
177
page = await new_context .new_page ()
172
178
else :
173
- await self ._ensure_browser_context ()
174
- page = await self . _browser_context .new_page ()
179
+ _browser_context = await self ._get_browser_context ()
180
+ page = await _browser_context .new_page ()
175
181
176
182
# Handle page close event
177
183
page .on (event = 'close' , f = self ._on_page_close )
@@ -181,7 +187,6 @@ async def new_page(
181
187
self ._last_page_opened_at = datetime .now (timezone .utc )
182
188
183
189
self ._total_opened_pages += 1
184
-
185
190
return page
186
191
187
192
@override
@@ -217,7 +222,6 @@ async def _create_browser_context(
217
222
Create context without headers and without fingerprints if neither `self._header_generator` nor
218
223
`self._fingerprint_generator` is available.
219
224
"""
220
- start = datetime .now (timezone .utc )
221
225
browser_new_context_options = dict (browser_new_context_options ) if browser_new_context_options else {}
222
226
if proxy_info :
223
227
if browser_new_context_options .get ('proxy' ):
@@ -230,14 +234,11 @@ async def _create_browser_context(
230
234
)
231
235
232
236
if self ._fingerprint_generator :
233
-
234
- c = await AsyncNewContext (
237
+ return await AsyncNewContext (
235
238
browser = self ._browser ,
236
239
fingerprint = self ._fingerprint_generator .generate (),
237
240
** browser_new_context_options ,
238
241
)
239
- logger .warning (f"Fingerprint generation time [s]: { (datetime .now (timezone .utc ) - start ).total_seconds ()} " )
240
- return c
241
242
242
243
if self ._header_generator :
243
244
extra_http_headers = dict (
@@ -259,5 +260,4 @@ async def _create_browser_context(
259
260
browser_new_context_options ['extra_http_headers' ] = browser_new_context_options .get (
260
261
'extra_http_headers' , extra_http_headers
261
262
)
262
- logger .warning (f"Fingerprint generation time [s]: { (datetime .now (timezone .utc )- start ).total_seconds ()} " )
263
263
return await self ._browser .new_context (** browser_new_context_options )
0 commit comments