wangweimin 5 سال پیش
والد
کامیت
c0493191da
5فایلهای تغییر یافته به همراه70 افزوده شده و 33 حذف شده
  1. 2 2
      pywebio/demos/overview-zh.py
  2. 0 30
      pywebio/ioloop.py
  3. 4 0
      pywebio/platform/__init__.py
  4. 51 1
      pywebio/platform/tornado.py
  5. 13 0
      pywebio/utils.py

+ 2 - 2
pywebio/demos/overview-zh.py

@@ -6,7 +6,7 @@ import asyncio
 from datetime import datetime
 from functools import partial
 from pywebio.input import *
-from pywebio.ioloop import start_ioloop
+from pywebio.platform import *
 from pywebio.session import *
 from pywebio.output import *
 
@@ -380,4 +380,4 @@ async def feature_overview():
     """, strip_indent=4)
 
 
-start_ioloop(feature_overview, debug=True)
+start_server(feature_overview, debug=True)

+ 0 - 30
pywebio/ioloop.py

@@ -1,30 +0,0 @@
-import tornado.websocket
-from tornado.web import StaticFileHandler
-from .session import AsyncBasedSession, get_session_implement
-from .platform import STATIC_PATH
-from .platform.tornado import webio_handler
-
-
-
-
-
-def start_ioloop(coro_func, port=8080, debug=True, tornado_app_args=None):
-    """
-    tornado app arg
-        websocket_max_message_size
-        ``websocket_ping_interval``, ``websocket_ping_timeout``, and
-       ``websocket_max_message_size``.
-
-    """
-    handlers = [(r"/io", webio_handler(coro_func)),
-                (r"/(.*)", StaticFileHandler, {"path": STATIC_PATH,
-                                               'default_filename': 'index.html'})]
-
-    tornado_app_args = tornado_app_args or {}
-    app = tornado.web.Application(handlers=handlers, debug=debug, **tornado_app_args)
-    http_server = tornado.httpserver.HTTPServer(app)
-    http_server.listen(port)
-
-    print('Open http://localhost:%s/ in Web browser' % port)
-
-    tornado.ioloop.IOLoop.instance().start()

+ 4 - 0
pywebio/platform/__init__.py

@@ -3,3 +3,7 @@ from os.path import abspath, dirname
 project_dir = dirname(dirname(abspath(__file__)))
 
 STATIC_PATH = '%s/html' % project_dir
+
+from .tornado import start_server
+
+__all__ = ['start_server']

+ 51 - 1
pywebio/platform/tornado.py

@@ -1,9 +1,12 @@
+import asyncio
 import json
 
-import asyncio
 import tornado
 import tornado.websocket
+from tornado.web import StaticFileHandler
+from . import STATIC_PATH
 from ..session import AsyncBasedSession, ThreadBasedWebIOSession, get_session_implement
+from ..utils import get_free_port
 
 
 def webio_handler(task_func, debug=True):
@@ -50,3 +53,50 @@ def webio_handler(task_func, debug=True):
             print("WebSocket closed")
 
     return WSHandler
+
+
+def start_server(target, port=0, host='', debug=True,
+                 websocket_max_message_size=None,
+                 websocket_ping_interval=None,
+                 websocket_ping_timeout=None,
+                 **tornado_app_settings):
+    """Start a Tornado server to serve `target` function
+
+    :param target: task function. It's a coroutine function is use AsyncBasedSession or
+        a simple function is use ThreadBasedWebIOSession.
+    :param port: server bind port. set ``0`` to find a free port number to use
+    :param host: server bind host. ``host`` may be either an IP address or hostname.  If it's a hostname,
+        the server will listen on all IP addresses associated with the name.
+        set empty string or to listen on all available interfaces.
+    :param debug: Tornado debug mode
+    :param int websocket_max_message_size: Max bytes of a message which Tornado can accept.
+        Messages larger than the ``websocket_max_message_size`` (default 10MiB) will not be accepted.
+    :param int websocket_ping_interval: If set to a number, all websockets will be pinged every n seconds.
+        This can help keep the connection alive through certain proxy servers which close idle connections,
+        and it can detect if the websocket has failed without being properly closed.
+    :param int websocket_ping_timeout: If the ping interval is set, and the server doesn’t receive a ‘pong’
+        in this many seconds, it will close the websocket. The default is three times the ping interval,
+        with a minimum of 30 seconds. Ignored if ``websocket_ping_interval`` is not set.
+    :param tornado_app_settings: Additional keyword arguments passed to the constructor of ``tornado.web.Application``.
+        ref: https://www.tornadoweb.org/en/stable/web.html#tornado.web.Application.settings
+    :return:
+    """
+    kwargs = locals()
+    app_options = ['debug', 'websocket_max_message_size', 'websocket_ping_interval', 'websocket_ping_timeout']
+    for opt in app_options:
+        if opt is not None:
+            tornado_app_settings[opt] = kwargs[opt]
+
+    if port == 0:
+        port = get_free_port()
+
+    handlers = [(r"/io", webio_handler(target)),
+                (r"/(.*)", StaticFileHandler, {"path": STATIC_PATH, 'default_filename': 'index.html'})]
+
+    app = tornado.web.Application(handlers=handlers, **tornado_app_settings)
+    http_server = tornado.httpserver.HTTPServer(app)
+    http_server.listen(port, address=host)
+
+    print('Listen on %s:%s' % (host or '0.0.0.0', port))
+
+    tornado.ioloop.IOLoop.instance().start()

+ 13 - 0
pywebio/utils.py

@@ -1,6 +1,19 @@
 import random
+import socket
 import string
 from collections import OrderedDict
+from contextlib import closing
+
+
+def get_free_port():
+    """
+    pick a free port number
+    :return int: port number
+    """
+    with closing(socket.socket(socket.AF_INET, socket.SOCK_STREAM)) as s:
+        s.bind(('', 0))
+        s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
+        return s.getsockname()[1]
 
 
 def random_str(len=16):