We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
Streamlit 0.49.0 on Windows + Python 3.8 fails to execute (Tornado error)
# Summary
Streamlit fails to execute on Windows under Python 3.8 due to a bug in Tornado.  The version of Tornado pinned in streamlit 0.49 was 5.x, while the latest version of Tornado at the time of this bug was 6.0.3.  [A similar bug was found in IPython notebook.](https://stackoverflow.com/questions/58422817/jupyter-notebook-with-python-3-8-notimplementederror)

# Steps to reproduce
What are the steps we should take to reproduce the bug:
1. Setup Python 3.8 virtualenv on Windows
2. Install streamlit 0.49.0
3. streamlit hello

## Expected behavior:
Streamlit hello should run.

## Actual behavior:
Streamlit fails to execute, spitting out the following (tail end of traceback -- [see full traceback here](https://discuss.streamlit.io/t/streamlit-issue-when-calling-streamlit/724)):

```
self._handlers[sock.fileno()] = add_accept_handler(
File “c:\users\admin\appdata\local\programs\python\python38-32\lib\site-packages\tornado\netutil.py”, line 268, in add_accept_handler
io_loop.add_handler(sock, accept_handler, IOLoop.READ)
File “c:\users\admin\appdata\local\programs\python\python38-32\lib\site-packages\tornado\platform\asyncio.py”, line 79, in add_handler
self.asyncio_loop.add_reader(
File “c:\users\admin\appdata\local\programs\python\python38-32\lib\asyncio\events.py”, line 501, in add_reader
raise NotImplementedError
NotImplementedError
```

## Is this a regression?

No; Python 3.8 hasn't been officially supported in Streamlit to date.  (But it _should_ work.)

# Debug info
- Streamlit version: 0.49.0
- Python version: 3.8
- Using Conda? PipEnv? PyEnv? Pex?  any
- OS version: Windows (probably any)
- Browser version:  n/a

# Additional information

Using Python 3.7.5 is the recommended solution for now.  See https://discuss.streamlit.io/t/streamlit-issue-when-calling-streamlit/724/4


--- END ISSUE ---

Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
--- BEGIN FILES ---
Path: `lib/streamlit/bootstrap.py`
Content:
```
1 # -*- coding: utf-8 -*-
2 # Copyright 2018-2019 Streamlit Inc.
3 #
4 # Licensed under the Apache License, Version 2.0 (the "License");
5 # you may not use this file except in compliance with the License.
6 # You may obtain a copy of the License at
7 #
8 #    http://www.apache.org/licenses/LICENSE-2.0
9 #
10 # Unless required by applicable law or agreed to in writing, software
11 # distributed under the License is distributed on an "AS IS" BASIS,
12 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 # See the License for the specific language governing permissions and
14 # limitations under the License.
15 
16 import os
17 import signal
18 import sys
19 
20 import click
21 import tornado.ioloop
22 
23 from streamlit import config
24 from streamlit import net_util
25 from streamlit import url_util
26 from streamlit import util
27 from streamlit.Report import Report
28 from streamlit.logger import get_logger
29 from streamlit.server.Server import Server
30 
31 LOGGER = get_logger(__name__)
32 
33 
34 # Wait for 1 second before opening a browser. This gives old tabs a chance to
35 # reconnect.
36 # This must be >= 2 * WebSocketConnection.ts#RECONNECT_WAIT_TIME_MS.
37 BROWSER_WAIT_TIMEOUT_SEC = 1
38 
39 
40 def _set_up_signal_handler():
41     LOGGER.debug("Setting up signal handler")
42 
43     def signal_handler(signal_number, stack_frame):
44         # The server will shut down its threads and stop the ioloop
45         Server.get_current().stop()
46 
47     signal.signal(signal.SIGTERM, signal_handler)
48     signal.signal(signal.SIGINT, signal_handler)
49     if sys.platform == "win32":
50         signal.signal(signal.SIGBREAK, signal_handler)
51     else:
52         signal.signal(signal.SIGQUIT, signal_handler)
53 
54 
55 def _fix_sys_path(script_path):
56     """Add the script's folder to the sys path.
57 
58     Python normally does this automatically, but since we exec the script
59     ourselves we need to do it instead.
60     """
61     sys.path.insert(0, os.path.dirname(script_path))
62 
63 
64 def _fix_matplotlib_crash():
65     """Set Matplotlib backend to avoid a crash.
66 
67     The default Matplotlib backend crashes Python on OSX when run on a thread
68     that's not the main thread, so here we set a safer backend as a fix.
69     Users can always disable this behavior by setting the config
70     runner.fixMatplotlib = false.
71 
72     This fix is OS-independent. We didn't see a good reason to make this
73     Mac-only. Consistency within Streamlit seemed more important.
74     """
75     if config.get_option("runner.fixMatplotlib"):
76         try:
77             # TODO: a better option may be to set
78             #  os.environ["MPLBACKEND"] = "Agg". We'd need to do this towards
79             #  the top of __init__.py, before importing anything that imports
80             #  pandas (which imports matplotlib). Alternately, we could set
81             #  this environment variable in a new entrypoint defined in
82             #  setup.py. Both of these introduce additional trickiness: they
83             #  need to run without consulting streamlit.config.get_option,
84             #  because this would import streamlit, and therefore matplotlib.
85             import matplotlib
86 
87             matplotlib.use("Agg")
88         except ImportError:
89             pass
90 
91 
92 def _fix_sys_argv(script_path, args):
93     """sys.argv needs to exclude streamlit arguments and parameters
94     and be set to what a user's script may expect.
95     """
96     import sys
97 
98     sys.argv = [script_path] + list(args)
99 
100 
101 def _on_server_start(server):
102     _print_url()
103 
104     def maybe_open_browser():
105         if config.get_option("server.headless"):
106             # Don't open browser when in headless mode.
107             return
108 
109         if server.browser_is_connected:
110             # Don't auto-open browser if there's already a browser connected.
111             # This can happen if there's an old tab repeatedly trying to
112             # connect, and it happens to success before we launch the browser.
113             return
114 
115         if config.is_manually_set("browser.serverAddress"):
116             addr = config.get_option("browser.serverAddress")
117         else:
118             addr = "localhost"
119 
120         util.open_browser(Report.get_url(addr))
121 
122     # Schedule the browser to open using the IO Loop on the main thread, but
123     # only if no other browser connects within 1s.
124     ioloop = tornado.ioloop.IOLoop.current()
125     ioloop.call_later(BROWSER_WAIT_TIMEOUT_SEC, maybe_open_browser)
126 
127 
128 def _print_url():
129     title_message = "You can now view your Streamlit app in your browser."
130     named_urls = []
131 
132     if config.is_manually_set("browser.serverAddress"):
133         named_urls = [
134             ("URL", Report.get_url(config.get_option("browser.serverAddress")))
135         ]
136 
137     elif config.get_option("server.headless"):
138         named_urls = [
139             ("Network URL", Report.get_url(net_util.get_internal_ip())),
140             ("External URL", Report.get_url(net_util.get_external_ip())),
141         ]
142 
143     else:
144         named_urls = [
145             ("Local URL", Report.get_url("localhost")),
146             ("Network URL", Report.get_url(net_util.get_internal_ip())),
147         ]
148 
149     click.secho("")
150     click.secho("  %s" % title_message, fg="blue", bold=True)
151     click.secho("")
152 
153     for url_name, url in named_urls:
154         url_util.print_url(url_name, url)
155 
156     click.secho("")
157 
158 
159 def run(script_path, command_line, args):
160     """Run a script in a separate thread and start a server for the app.
161 
162     This starts a blocking ioloop.
163 
164     Parameters
165     ----------
166     script_path : str
167     command_line : str
168     args : [str]
169 
170     """
171     _fix_sys_path(script_path)
172     _fix_matplotlib_crash()
173     _fix_sys_argv(script_path, args)
174 
175     # Install a signal handler that will shut down the ioloop
176     # and close all our threads
177     _set_up_signal_handler()
178 
179     ioloop = tornado.ioloop.IOLoop.current()
180 
181     # Create and start the server.
182     server = Server(ioloop, script_path, command_line)
183     server.start(_on_server_start)
184 
185     # (Must com after start(), because this starts a new thread and start() may
186     # call sys.exit() which doesn't kill other threads.
187     server.add_preheated_report_session()
188 
189     # Start the ioloop. This function will not return until the
190     # server is shut down.
191     ioloop.start()
192
```
--- END FILES ---

Please first localize the bug based on the issue statement, and then generate a patch according to the `git diff` format fenced by three backticks.

Here is an example:

```diff
diff --git a/examples/server_async.py b/examples/server_async.py
--- a/examples/server_async.py
+++ b/examples/server_async.py
@@ -313,4 +313,4 @@
 
 
 if __name__ == "__main__":
-    asyncio.run(run_async_server("."), debug=True)
+    asyncio.run(run_async_server(), debug=True)
diff --git a/examples/server_sync.py b/examples/server_sync.py
--- a/examples/server_sync.py
+++ b/examples/server_sync.py
@@ -313,5 +313,5 @@
 
 
 if __name__ == "__main__":
-    server = run_sync_server(".")
+    server = run_sync_server()
     server.shutdown()

```

diff --git a/lib/streamlit/bootstrap.py b/lib/streamlit/bootstrap.py
--- a/lib/streamlit/bootstrap.py
+++ b/lib/streamlit/bootstrap.py
@@ -23,6 +23,7 @@
 from streamlit import config
 from streamlit import net_util
 from streamlit import url_util
+from streamlit import env_util
 from streamlit import util
 from streamlit.Report import Report
 from streamlit.logger import get_logger
@@ -30,7 +31,6 @@
 
 LOGGER = get_logger(__name__)
 
-
 # Wait for 1 second before opening a browser. This gives old tabs a chance to
 # reconnect.
 # This must be >= 2 * WebSocketConnection.ts#RECONNECT_WAIT_TIME_MS.
@@ -89,6 +89,43 @@
             pass
 
 
+def _fix_tornado_crash():
+    """Set default asyncio policy to be compatible with Tornado 6.
+
+        Tornado 6 (at least) is not compatible with the default
+        asyncio implementation on Windows. So here we
+        pick the older SelectorEventLoopPolicy when the OS is Windows
+        if the known-incompatible default policy is in use.
+
+        This has to happen as early as possible to make it a low priority and
+        overrideable
+
+        See: https://github.com/tornadoweb/tornado/issues/2608
+
+        FIXME: if/when tornado supports the defaults in asyncio,
+        remove and bump tornado requirement for py38
+    """
+    if env_util.IS_WINDOWS and sys.version_info >= (3, 8):
+        import asyncio
+        try:
+            from asyncio import (
+                WindowsProactorEventLoopPolicy,
+                WindowsSelectorEventLoopPolicy,
+            )
+        except ImportError:
+            pass
+            # Not affected
+        else:
+            if (
+                type(asyncio.get_event_loop_policy()) is
+                    WindowsProactorEventLoopPolicy
+            ):
+                # WindowsProactorEventLoopPolicy is not compatible with
+                # Tornado 6 fallback to the pre-3.8 default of Selector
+                asyncio.set_event_loop_policy(
+                    WindowsSelectorEventLoopPolicy())
+
+
 def _fix_sys_argv(script_path, args):
     """sys.argv needs to exclude streamlit arguments and parameters
     and be set to what a user's script may expect.
@@ -170,6 +207,7 @@
     """
     _fix_sys_path(script_path)
     _fix_matplotlib_crash()
+    _fix_tornado_crash()
     _fix_sys_argv(script_path, args)
 
     # Install a signal handler that will shut down the ioloop

{"golden_diff": "diff --git a/lib/streamlit/bootstrap.py b/lib/streamlit/bootstrap.py\n--- a/lib/streamlit/bootstrap.py\n+++ b/lib/streamlit/bootstrap.py\n@@ -23,6 +23,7 @@\n from streamlit import config\n from streamlit import net_util\n from streamlit import url_util\n+from streamlit import env_util\n from streamlit import util\n from streamlit.Report import Report\n from streamlit.logger import get_logger\n@@ -30,7 +31,6 @@\n \n LOGGER = get_logger(__name__)\n \n-\n # Wait for 1 second before opening a browser. This gives old tabs a chance to\n # reconnect.\n # This must be >= 2 * WebSocketConnection.ts#RECONNECT_WAIT_TIME_MS.\n@@ -89,6 +89,43 @@\n             pass\n \n \n+def _fix_tornado_crash():\n+    \"\"\"Set default asyncio policy to be compatible with Tornado 6.\n+\n+        Tornado 6 (at least) is not compatible with the default\n+        asyncio implementation on Windows. So here we\n+        pick the older SelectorEventLoopPolicy when the OS is Windows\n+        if the known-incompatible default policy is in use.\n+\n+        This has to happen as early as possible to make it a low priority and\n+        overrideable\n+\n+        See: https://github.com/tornadoweb/tornado/issues/2608\n+\n+        FIXME: if/when tornado supports the defaults in asyncio,\n+        remove and bump tornado requirement for py38\n+    \"\"\"\n+    if env_util.IS_WINDOWS and sys.version_info >= (3, 8):\n+        import asyncio\n+        try:\n+            from asyncio import (\n+                WindowsProactorEventLoopPolicy,\n+                WindowsSelectorEventLoopPolicy,\n+            )\n+        except ImportError:\n+            pass\n+            # Not affected\n+        else:\n+            if (\n+                type(asyncio.get_event_loop_policy()) is\n+                    WindowsProactorEventLoopPolicy\n+            ):\n+                # WindowsProactorEventLoopPolicy is not compatible with\n+                # Tornado 6 fallback to the pre-3.8 default of Selector\n+                asyncio.set_event_loop_policy(\n+                    WindowsSelectorEventLoopPolicy())\n+\n+\n def _fix_sys_argv(script_path, args):\n     \"\"\"sys.argv needs to exclude streamlit arguments and parameters\n     and be set to what a user's script may expect.\n@@ -170,6 +207,7 @@\n     \"\"\"\n     _fix_sys_path(script_path)\n     _fix_matplotlib_crash()\n+    _fix_tornado_crash()\n     _fix_sys_argv(script_path, args)\n \n     # Install a signal handler that will shut down the ioloop\n", "issue": "Streamlit 0.49.0 on Windows + Python 3.8 fails to execute (Tornado error)\n# Summary\r\nStreamlit fails to execute on Windows under Python 3.8 due to a bug in Tornado.  The version of Tornado pinned in streamlit 0.49 was 5.x, while the latest version of Tornado at the time of this bug was 6.0.3.  [A similar bug was found in IPython notebook.](https://stackoverflow.com/questions/58422817/jupyter-notebook-with-python-3-8-notimplementederror)\r\n\r\n# Steps to reproduce\r\nWhat are the steps we should take to reproduce the bug:\r\n1. Setup Python 3.8 virtualenv on Windows\r\n2. Install streamlit 0.49.0\r\n3. streamlit hello\r\n\r\n## Expected behavior:\r\nStreamlit hello should run.\r\n\r\n## Actual behavior:\r\nStreamlit fails to execute, spitting out the following (tail end of traceback -- [see full traceback here](https://discuss.streamlit.io/t/streamlit-issue-when-calling-streamlit/724)):\r\n\r\n```\r\nself._handlers[sock.fileno()] = add_accept_handler(\r\nFile \u201cc:\\users\\admin\\appdata\\local\\programs\\python\\python38-32\\lib\\site-packages\\tornado\\netutil.py\u201d, line 268, in add_accept_handler\r\nio_loop.add_handler(sock, accept_handler, IOLoop.READ)\r\nFile \u201cc:\\users\\admin\\appdata\\local\\programs\\python\\python38-32\\lib\\site-packages\\tornado\\platform\\asyncio.py\u201d, line 79, in add_handler\r\nself.asyncio_loop.add_reader(\r\nFile \u201cc:\\users\\admin\\appdata\\local\\programs\\python\\python38-32\\lib\\asyncio\\events.py\u201d, line 501, in add_reader\r\nraise NotImplementedError\r\nNotImplementedError\r\n```\r\n\r\n## Is this a regression?\r\n\r\nNo; Python 3.8 hasn't been officially supported in Streamlit to date.  (But it _should_ work.)\r\n\r\n# Debug info\r\n- Streamlit version: 0.49.0\r\n- Python version: 3.8\r\n- Using Conda? PipEnv? PyEnv? Pex?  any\r\n- OS version: Windows (probably any)\r\n- Browser version:  n/a\r\n\r\n# Additional information\r\n\r\nUsing Python 3.7.5 is the recommended solution for now.  See https://discuss.streamlit.io/t/streamlit-issue-when-calling-streamlit/724/4\r\n\n", "before_files": [{"content": "# -*- coding: utf-8 -*-\n# Copyright 2018-2019 Streamlit Inc.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#    http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n\nimport os\nimport signal\nimport sys\n\nimport click\nimport tornado.ioloop\n\nfrom streamlit import config\nfrom streamlit import net_util\nfrom streamlit import url_util\nfrom streamlit import util\nfrom streamlit.Report import Report\nfrom streamlit.logger import get_logger\nfrom streamlit.server.Server import Server\n\nLOGGER = get_logger(__name__)\n\n\n# Wait for 1 second before opening a browser. This gives old tabs a chance to\n# reconnect.\n# This must be >= 2 * WebSocketConnection.ts#RECONNECT_WAIT_TIME_MS.\nBROWSER_WAIT_TIMEOUT_SEC = 1\n\n\ndef _set_up_signal_handler():\n    LOGGER.debug(\"Setting up signal handler\")\n\n    def signal_handler(signal_number, stack_frame):\n        # The server will shut down its threads and stop the ioloop\n        Server.get_current().stop()\n\n    signal.signal(signal.SIGTERM, signal_handler)\n    signal.signal(signal.SIGINT, signal_handler)\n    if sys.platform == \"win32\":\n        signal.signal(signal.SIGBREAK, signal_handler)\n    else:\n        signal.signal(signal.SIGQUIT, signal_handler)\n\n\ndef _fix_sys_path(script_path):\n    \"\"\"Add the script's folder to the sys path.\n\n    Python normally does this automatically, but since we exec the script\n    ourselves we need to do it instead.\n    \"\"\"\n    sys.path.insert(0, os.path.dirname(script_path))\n\n\ndef _fix_matplotlib_crash():\n    \"\"\"Set Matplotlib backend to avoid a crash.\n\n    The default Matplotlib backend crashes Python on OSX when run on a thread\n    that's not the main thread, so here we set a safer backend as a fix.\n    Users can always disable this behavior by setting the config\n    runner.fixMatplotlib = false.\n\n    This fix is OS-independent. We didn't see a good reason to make this\n    Mac-only. Consistency within Streamlit seemed more important.\n    \"\"\"\n    if config.get_option(\"runner.fixMatplotlib\"):\n        try:\n            # TODO: a better option may be to set\n            #  os.environ[\"MPLBACKEND\"] = \"Agg\". We'd need to do this towards\n            #  the top of __init__.py, before importing anything that imports\n            #  pandas (which imports matplotlib). Alternately, we could set\n            #  this environment variable in a new entrypoint defined in\n            #  setup.py. Both of these introduce additional trickiness: they\n            #  need to run without consulting streamlit.config.get_option,\n            #  because this would import streamlit, and therefore matplotlib.\n            import matplotlib\n\n            matplotlib.use(\"Agg\")\n        except ImportError:\n            pass\n\n\ndef _fix_sys_argv(script_path, args):\n    \"\"\"sys.argv needs to exclude streamlit arguments and parameters\n    and be set to what a user's script may expect.\n    \"\"\"\n    import sys\n\n    sys.argv = [script_path] + list(args)\n\n\ndef _on_server_start(server):\n    _print_url()\n\n    def maybe_open_browser():\n        if config.get_option(\"server.headless\"):\n            # Don't open browser when in headless mode.\n            return\n\n        if server.browser_is_connected:\n            # Don't auto-open browser if there's already a browser connected.\n            # This can happen if there's an old tab repeatedly trying to\n            # connect, and it happens to success before we launch the browser.\n            return\n\n        if config.is_manually_set(\"browser.serverAddress\"):\n            addr = config.get_option(\"browser.serverAddress\")\n        else:\n            addr = \"localhost\"\n\n        util.open_browser(Report.get_url(addr))\n\n    # Schedule the browser to open using the IO Loop on the main thread, but\n    # only if no other browser connects within 1s.\n    ioloop = tornado.ioloop.IOLoop.current()\n    ioloop.call_later(BROWSER_WAIT_TIMEOUT_SEC, maybe_open_browser)\n\n\ndef _print_url():\n    title_message = \"You can now view your Streamlit app in your browser.\"\n    named_urls = []\n\n    if config.is_manually_set(\"browser.serverAddress\"):\n        named_urls = [\n            (\"URL\", Report.get_url(config.get_option(\"browser.serverAddress\")))\n        ]\n\n    elif config.get_option(\"server.headless\"):\n        named_urls = [\n            (\"Network URL\", Report.get_url(net_util.get_internal_ip())),\n            (\"External URL\", Report.get_url(net_util.get_external_ip())),\n        ]\n\n    else:\n        named_urls = [\n            (\"Local URL\", Report.get_url(\"localhost\")),\n            (\"Network URL\", Report.get_url(net_util.get_internal_ip())),\n        ]\n\n    click.secho(\"\")\n    click.secho(\"  %s\" % title_message, fg=\"blue\", bold=True)\n    click.secho(\"\")\n\n    for url_name, url in named_urls:\n        url_util.print_url(url_name, url)\n\n    click.secho(\"\")\n\n\ndef run(script_path, command_line, args):\n    \"\"\"Run a script in a separate thread and start a server for the app.\n\n    This starts a blocking ioloop.\n\n    Parameters\n    ----------\n    script_path : str\n    command_line : str\n    args : [str]\n\n    \"\"\"\n    _fix_sys_path(script_path)\n    _fix_matplotlib_crash()\n    _fix_sys_argv(script_path, args)\n\n    # Install a signal handler that will shut down the ioloop\n    # and close all our threads\n    _set_up_signal_handler()\n\n    ioloop = tornado.ioloop.IOLoop.current()\n\n    # Create and start the server.\n    server = Server(ioloop, script_path, command_line)\n    server.start(_on_server_start)\n\n    # (Must com after start(), because this starts a new thread and start() may\n    # call sys.exit() which doesn't kill other threads.\n    server.add_preheated_report_session()\n\n    # Start the ioloop. This function will not return until the\n    # server is shut down.\n    ioloop.start()\n", "path": "lib/streamlit/bootstrap.py"}], "after_files": [{"content": "# -*- coding: utf-8 -*-\n# Copyright 2018-2019 Streamlit Inc.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#    http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n\nimport os\nimport signal\nimport sys\n\nimport click\nimport tornado.ioloop\n\nfrom streamlit import config\nfrom streamlit import net_util\nfrom streamlit import url_util\nfrom streamlit import env_util\nfrom streamlit import util\nfrom streamlit.Report import Report\nfrom streamlit.logger import get_logger\nfrom streamlit.server.Server import Server\n\nLOGGER = get_logger(__name__)\n\n# Wait for 1 second before opening a browser. This gives old tabs a chance to\n# reconnect.\n# This must be >= 2 * WebSocketConnection.ts#RECONNECT_WAIT_TIME_MS.\nBROWSER_WAIT_TIMEOUT_SEC = 1\n\n\ndef _set_up_signal_handler():\n    LOGGER.debug(\"Setting up signal handler\")\n\n    def signal_handler(signal_number, stack_frame):\n        # The server will shut down its threads and stop the ioloop\n        Server.get_current().stop()\n\n    signal.signal(signal.SIGTERM, signal_handler)\n    signal.signal(signal.SIGINT, signal_handler)\n    if sys.platform == \"win32\":\n        signal.signal(signal.SIGBREAK, signal_handler)\n    else:\n        signal.signal(signal.SIGQUIT, signal_handler)\n\n\ndef _fix_sys_path(script_path):\n    \"\"\"Add the script's folder to the sys path.\n\n    Python normally does this automatically, but since we exec the script\n    ourselves we need to do it instead.\n    \"\"\"\n    sys.path.insert(0, os.path.dirname(script_path))\n\n\ndef _fix_matplotlib_crash():\n    \"\"\"Set Matplotlib backend to avoid a crash.\n\n    The default Matplotlib backend crashes Python on OSX when run on a thread\n    that's not the main thread, so here we set a safer backend as a fix.\n    Users can always disable this behavior by setting the config\n    runner.fixMatplotlib = false.\n\n    This fix is OS-independent. We didn't see a good reason to make this\n    Mac-only. Consistency within Streamlit seemed more important.\n    \"\"\"\n    if config.get_option(\"runner.fixMatplotlib\"):\n        try:\n            # TODO: a better option may be to set\n            #  os.environ[\"MPLBACKEND\"] = \"Agg\". We'd need to do this towards\n            #  the top of __init__.py, before importing anything that imports\n            #  pandas (which imports matplotlib). Alternately, we could set\n            #  this environment variable in a new entrypoint defined in\n            #  setup.py. Both of these introduce additional trickiness: they\n            #  need to run without consulting streamlit.config.get_option,\n            #  because this would import streamlit, and therefore matplotlib.\n            import matplotlib\n\n            matplotlib.use(\"Agg\")\n        except ImportError:\n            pass\n\n\ndef _fix_tornado_crash():\n    \"\"\"Set default asyncio policy to be compatible with Tornado 6.\n\n        Tornado 6 (at least) is not compatible with the default\n        asyncio implementation on Windows. So here we\n        pick the older SelectorEventLoopPolicy when the OS is Windows\n        if the known-incompatible default policy is in use.\n\n        This has to happen as early as possible to make it a low priority and\n        overrideable\n\n        See: https://github.com/tornadoweb/tornado/issues/2608\n\n        FIXME: if/when tornado supports the defaults in asyncio,\n        remove and bump tornado requirement for py38\n    \"\"\"\n    if env_util.IS_WINDOWS and sys.version_info >= (3, 8):\n        import asyncio\n        try:\n            from asyncio import (\n                WindowsProactorEventLoopPolicy,\n                WindowsSelectorEventLoopPolicy,\n            )\n        except ImportError:\n            pass\n            # Not affected\n        else:\n            if (\n                type(asyncio.get_event_loop_policy()) is\n                    WindowsProactorEventLoopPolicy\n            ):\n                # WindowsProactorEventLoopPolicy is not compatible with\n                # Tornado 6 fallback to the pre-3.8 default of Selector\n                asyncio.set_event_loop_policy(\n                    WindowsSelectorEventLoopPolicy())\n\n\ndef _fix_sys_argv(script_path, args):\n    \"\"\"sys.argv needs to exclude streamlit arguments and parameters\n    and be set to what a user's script may expect.\n    \"\"\"\n    import sys\n\n    sys.argv = [script_path] + list(args)\n\n\ndef _on_server_start(server):\n    _print_url()\n\n    def maybe_open_browser():\n        if config.get_option(\"server.headless\"):\n            # Don't open browser when in headless mode.\n            return\n\n        if server.browser_is_connected:\n            # Don't auto-open browser if there's already a browser connected.\n            # This can happen if there's an old tab repeatedly trying to\n            # connect, and it happens to success before we launch the browser.\n            return\n\n        if config.is_manually_set(\"browser.serverAddress\"):\n            addr = config.get_option(\"browser.serverAddress\")\n        else:\n            addr = \"localhost\"\n\n        util.open_browser(Report.get_url(addr))\n\n    # Schedule the browser to open using the IO Loop on the main thread, but\n    # only if no other browser connects within 1s.\n    ioloop = tornado.ioloop.IOLoop.current()\n    ioloop.call_later(BROWSER_WAIT_TIMEOUT_SEC, maybe_open_browser)\n\n\ndef _print_url():\n    title_message = \"You can now view your Streamlit app in your browser.\"\n    named_urls = []\n\n    if config.is_manually_set(\"browser.serverAddress\"):\n        named_urls = [\n            (\"URL\", Report.get_url(config.get_option(\"browser.serverAddress\")))\n        ]\n\n    elif config.get_option(\"server.headless\"):\n        named_urls = [\n            (\"Network URL\", Report.get_url(net_util.get_internal_ip())),\n            (\"External URL\", Report.get_url(net_util.get_external_ip())),\n        ]\n\n    else:\n        named_urls = [\n            (\"Local URL\", Report.get_url(\"localhost\")),\n            (\"Network URL\", Report.get_url(net_util.get_internal_ip())),\n        ]\n\n    click.secho(\"\")\n    click.secho(\"  %s\" % title_message, fg=\"blue\", bold=True)\n    click.secho(\"\")\n\n    for url_name, url in named_urls:\n        url_util.print_url(url_name, url)\n\n    click.secho(\"\")\n\n\ndef run(script_path, command_line, args):\n    \"\"\"Run a script in a separate thread and start a server for the app.\n\n    This starts a blocking ioloop.\n\n    Parameters\n    ----------\n    script_path : str\n    command_line : str\n    args : [str]\n\n    \"\"\"\n    _fix_sys_path(script_path)\n    _fix_matplotlib_crash()\n    _fix_tornado_crash()\n    _fix_sys_argv(script_path, args)\n\n    # Install a signal handler that will shut down the ioloop\n    # and close all our threads\n    _set_up_signal_handler()\n\n    ioloop = tornado.ioloop.IOLoop.current()\n\n    # Create and start the server.\n    server = Server(ioloop, script_path, command_line)\n    server.start(_on_server_start)\n\n    # (Must com after start(), because this starts a new thread and start() may\n    # call sys.exit() which doesn't kill other threads.\n    server.add_preheated_report_session()\n\n    # Start the ioloop. This function will not return until the\n    # server is shut down.\n    ioloop.start()\n", "path": "lib/streamlit/bootstrap.py"}]}