@@ -635,6 +635,36 @@ def configure_tornado_logger(self):
635635 handler .setFormatter (formatter )
636636 logger .addHandler (handler )
637637
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+
638668 def init_pdb (self ):
639669 """Replace pdb with IPython's version that is interruptible.
640670
@@ -654,6 +684,7 @@ def init_pdb(self):
654684 @catch_config_error
655685 def initialize (self , argv = None ):
656686 """Initialize the application."""
687+ self ._init_asyncio_patch ()
657688 super ().initialize (argv )
658689 if self .subapp is not None :
659690 return
0 commit comments