@@ -635,6 +635,36 @@ def configure_tornado_logger(self):
635
635
handler .setFormatter (formatter )
636
636
logger .addHandler (handler )
637
637
638
+ def _init_asyncio_patch (self ):
639
+ """set default asyncio policy to be compatible with tornado
640
+ Tornado 6 (at least) is not compatible with the default
641
+ asyncio implementation on Windows
642
+ Pick the older SelectorEventLoopPolicy on Windows
643
+ if the known-incompatible default policy is in use.
644
+ Support for Proactor via a background thread is available in tornado 6.1,
645
+ but it is still preferable to run the Selector in the main thread
646
+ instead of the background.
647
+ do this as early as possible to make it a low priority and overridable
648
+ ref: https://github.com/tornadoweb/tornado/issues/2608
649
+ FIXME: if/when tornado supports the defaults in asyncio without threads,
650
+ remove and bump tornado requirement for py38.
651
+ Most likely, this will mean a new Python version
652
+ where asyncio.ProactorEventLoop supports add_reader and friends.
653
+ """
654
+ if sys .platform .startswith ("win" ):
655
+ import asyncio
656
+
657
+ try :
658
+ from asyncio import WindowsProactorEventLoopPolicy , WindowsSelectorEventLoopPolicy
659
+ except ImportError :
660
+ pass
661
+ # not affected
662
+ else :
663
+ if type (asyncio .get_event_loop_policy ()) is WindowsProactorEventLoopPolicy :
664
+ # WindowsProactorEventLoopPolicy is not compatible with tornado 6
665
+ # fallback to the pre-3.8 default of Selector
666
+ asyncio .set_event_loop_policy (WindowsSelectorEventLoopPolicy ())
667
+
638
668
def init_pdb (self ):
639
669
"""Replace pdb with IPython's version that is interruptible.
640
670
@@ -654,6 +684,7 @@ def init_pdb(self):
654
684
@catch_config_error
655
685
def initialize (self , argv = None ):
656
686
"""Initialize the application."""
687
+ self ._init_asyncio_patch ()
657
688
super ().initialize (argv )
658
689
if self .subapp is not None :
659
690
return
0 commit comments