@@ -258,11 +258,15 @@ def start_polling(self,
258
258
# Create & start threads
259
259
self .job_queue .start ()
260
260
dispatcher_ready = Event ()
261
+ polling_ready = Event ()
261
262
self ._init_thread (self .dispatcher .start , "dispatcher" , ready = dispatcher_ready )
262
263
self ._init_thread (self ._start_polling , "updater" , poll_interval , timeout ,
263
- read_latency , bootstrap_retries , clean , allowed_updates )
264
+ read_latency , bootstrap_retries , clean , allowed_updates ,
265
+ ready = polling_ready )
264
266
267
+ self .logger .debug ('Waiting for Dispatcher and polling to start' )
265
268
dispatcher_ready .wait ()
269
+ polling_ready .wait ()
266
270
267
271
# Return the update queue so the main thread can insert updates
268
272
return self .update_queue
@@ -276,14 +280,24 @@ def start_webhook(self,
276
280
clean = False ,
277
281
bootstrap_retries = 0 ,
278
282
webhook_url = None ,
279
- allowed_updates = None ):
283
+ allowed_updates = None ,
284
+ force_event_loop = False ):
280
285
"""
281
286
Starts a small http server to listen for updates via webhook. If cert
282
287
and key are not provided, the webhook will be started directly on
283
288
http://listen:port/url_path, so SSL can be handled by another
284
289
application. Else, the webhook will be started on
285
290
https://listen:port/url_path
286
291
292
+ Note:
293
+ Due to an incompatibility of the Tornado library PTB uses for the webhook with Python
294
+ 3.8+ on Windows machines, PTB will attempt to set the event loop to
295
+ :attr:`asyncio.SelectorEventLoop` and raise an exception, if an incompatible event loop
296
+ has already been specified. See this `thread`_ for more details. To suppress the
297
+ exception, set :attr:`force_event_loop` to :obj:`True`.
298
+
299
+ .. _thread: https://github.com/tornadoweb/tornado/issues/2608
300
+
287
301
Args:
288
302
listen (:obj:`str`, optional): IP-Address to listen on. Default ``127.0.0.1``.
289
303
port (:obj:`int`, optional): Port the bot should be listening on. Default ``80``.
@@ -303,6 +317,8 @@ def start_webhook(self,
303
317
NAT, reverse proxy, etc. Default is derived from `listen`, `port` & `url_path`.
304
318
allowed_updates (List[:obj:`str`], optional): Passed to
305
319
:attr:`telegram.Bot.set_webhook`.
320
+ force_event_loop (:obj:`bool`, optional): Force using the current event loop. See above
321
+ note for details. Defaults to :obj:`False`
306
322
307
323
Returns:
308
324
:obj:`Queue`: The update queue that can be filled from the main thread.
@@ -313,16 +329,23 @@ def start_webhook(self,
313
329
self .running = True
314
330
315
331
# Create & start threads
332
+ webhook_ready = Event ()
333
+ dispatcher_ready = Event ()
316
334
self .job_queue .start ()
317
- self ._init_thread (self .dispatcher .start , "dispatcher" ),
335
+ self ._init_thread (self .dispatcher .start , "dispatcher" , dispatcher_ready )
318
336
self ._init_thread (self ._start_webhook , "updater" , listen , port , url_path , cert ,
319
- key , bootstrap_retries , clean , webhook_url , allowed_updates )
337
+ key , bootstrap_retries , clean , webhook_url , allowed_updates ,
338
+ ready = webhook_ready , force_event_loop = force_event_loop )
339
+
340
+ self .logger .debug ('Waiting for Dispatcher and Webhook to start' )
341
+ webhook_ready .wait ()
342
+ dispatcher_ready .wait ()
320
343
321
344
# Return the update queue so the main thread can insert updates
322
345
return self .update_queue
323
346
324
347
def _start_polling (self , poll_interval , timeout , read_latency , bootstrap_retries , clean ,
325
- allowed_updates ): # pragma: no cover
348
+ allowed_updates , ready = None ): # pragma: no cover
326
349
# Thread target of thread 'updater'. Runs in background, pulls
327
350
# updates from Telegram and inserts them in the update queue of the
328
351
# Dispatcher.
@@ -354,6 +377,9 @@ def polling_onerr_cb(exc):
354
377
# broadcast it
355
378
self .update_queue .put (exc )
356
379
380
+ if ready is not None :
381
+ ready .set ()
382
+
357
383
self ._network_loop_retry (polling_action_cb , polling_onerr_cb , 'getting Updates' ,
358
384
poll_interval )
359
385
@@ -410,7 +436,7 @@ def _increase_poll_interval(current_interval):
410
436
return current_interval
411
437
412
438
def _start_webhook (self , listen , port , url_path , cert , key , bootstrap_retries , clean ,
413
- webhook_url , allowed_updates ):
439
+ webhook_url , allowed_updates , ready = None , force_event_loop = False ):
414
440
self .logger .debug ('Updater thread started (webhook)' )
415
441
use_ssl = cert is not None and key is not None
416
442
if not url_path .startswith ('/' ):
@@ -448,7 +474,7 @@ def _start_webhook(self, listen, port, url_path, cert, key, bootstrap_retries, c
448
474
self .logger .warning ("cleaning updates is not supported if "
449
475
"SSL-termination happens elsewhere; skipping" )
450
476
451
- self .httpd .serve_forever ()
477
+ self .httpd .serve_forever (force_event_loop = force_event_loop , ready = ready )
452
478
453
479
@staticmethod
454
480
def _gen_webhook_url (listen , port , url_path ):
0 commit comments