1
0

run.py 3.1 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889
  1. import inspect
  2. import logging
  3. import os
  4. import sys
  5. import webbrowser
  6. from typing import List, Optional
  7. import uvicorn
  8. from uvicorn.main import STARTUP_FAILURE
  9. from uvicorn.supervisors import ChangeReload, Multiprocess
  10. from . import globals
  11. from .config import Config
  12. os.environ['STATIC_DIRECTORY'] = os.path.join(os.path.dirname(os.path.realpath(__file__)), 'static')
  13. os.environ['TEMPLATES_DIRECTORY'] = os.path.join(os.environ['STATIC_DIRECTORY'], 'templates')
  14. def run(self, *,
  15. host: str = os.environ.get('HOST', '0.0.0.0'),
  16. port: int = int(os.environ.get('PORT', '8080')),
  17. title: str = 'NiceGUI',
  18. favicon: str = 'favicon.ico',
  19. dark: Optional[bool] = False,
  20. main_page_classes: str = 'q-ma-md column items-start',
  21. binding_refresh_interval: float = 0.1,
  22. show: bool = True,
  23. reload: bool = True,
  24. uvicorn_logging_level: str = 'warning',
  25. uvicorn_reload_dirs: str = '.',
  26. uvicorn_reload_includes: str = '*.py',
  27. uvicorn_reload_excludes: str = '.*, .py[cod], .sw.*, ~*',
  28. exclude: str = '',
  29. ):
  30. globals.config = Config(
  31. host=host,
  32. port=port,
  33. title=title,
  34. reload=reload,
  35. favicon=favicon,
  36. dark=dark,
  37. main_page_classes=main_page_classes,
  38. binding_refresh_interval=binding_refresh_interval,
  39. excludes=[e.strip() for e in exclude.split(',')],
  40. )
  41. os.environ['HOST'] = globals.config.host
  42. os.environ['PORT'] = str(globals.config.port)
  43. if inspect.stack()[-2].filename.endswith('spawn.py'):
  44. return
  45. if show:
  46. webbrowser.open(f'http://{host if host != "0.0.0.0" else "127.0.0.1"}:{port}/')
  47. def split_args(args: str) -> List[str]:
  48. return args.split(',') if ',' in args else [args]
  49. # NOTE: The following lines are basically a copy of `uvicorn.run`, but keep a reference to the `server`.
  50. config = uvicorn.Config(
  51. 'nicegui:app' if reload else globals.app,
  52. host=host,
  53. port=port,
  54. lifespan='on',
  55. reload=reload,
  56. reload_includes=split_args(uvicorn_reload_includes) if reload else None,
  57. reload_excludes=split_args(uvicorn_reload_excludes) if reload else None,
  58. reload_dirs=split_args(uvicorn_reload_dirs) if reload else None,
  59. log_level=uvicorn_logging_level,
  60. )
  61. globals.server = uvicorn.Server(config=config)
  62. if (reload or config.workers > 1) and not isinstance(config.app, str):
  63. logging.warning('You must pass the application as an import string to enable "reload" or "workers".')
  64. sys.exit(1)
  65. if config.should_reload:
  66. sock = config.bind_socket()
  67. ChangeReload(config, target=globals.server.run, sockets=[sock]).run()
  68. elif config.workers > 1:
  69. sock = config.bind_socket()
  70. Multiprocess(config, target=globals.server.run, sockets=[sock]).run()
  71. else:
  72. globals.server.run()
  73. if config.uds:
  74. os.remove(config.uds) # pragma: py-win32
  75. if not globals.server.started and not config.should_reload and config.workers == 1:
  76. sys.exit(STARTUP_FAILURE)