usr bin python coding utf-8 werkzeug serving There are many ways to se

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
#!/usr/bin/python
# -*- coding: utf-8 -*-
"""
werkzeug.serving
~~~~~~~~~~~~~~~~
There are many ways to serve a WSGI application. While you're developing
it you usually don't want a full blown webserver like Apache but a simple
standalone one. With Python 2.5 onwards there is the `wsgiref`_ server in
the standard library. If you're using older versions of Python you can
download the package from the cheeseshop.
However there are some caveats. Sourcecode won't reload itself when
changed and each time you kill the server using ``^C`` you get an
`KeyboardInterrupt` error. While the latter is easy to solve the first
one can be a pain in the ass in some situations.
Because of that Werkzeug ships a small wrapper over `wsgiref` that spawns
the WSGI application in a subprocess and automatically reloads the
application if a module was changed.
The easiest way is creating a small ``start-myproject.py`` that runs the
application::
#!/usr/bin/env python
# -*- coding: utf-8 -*-
from myproject import make_app
from werkzeug import run_simple
app = make_app(...)
run_simple('localhost', 8080, app, use_reloader=True)
You can also pass it a `extra_files` keyword argument with a list of
additional files (like configuration files) you want to observe.
For bigger applications you should consider using `werkzeug.script`
instead of a simple start file.
.. _wsgiref: http://cheeseshop.python.org/pypi/wsgiref
:copyright: (c) 2009 by the Werkzeug Team, see AUTHORS for more details.
:license: BSD, see LICENSE for more details.
"""
import os
import socket
import sys
import time
import thread
from itertools import chain
try:
from wsgiref.simple_server import ServerHandler, WSGIRequestHandler, \
WSGIServer
have_wsgiref = True
except ImportError:
have_wsgiref = False
from SocketServer import ThreadingMixIn, ForkingMixIn
_logger = None
def _log(type, message, *args, **kwargs):
"""Log into the internal werkzeug logger."""
global _logger
if _logger is None:
import logging
_logger = logging.getLogger('werkzeug')
if _logger.getEffectiveLevel() == logging.NOTSET:
_logger.setLevel(logging.INFO)
handler = logging.StreamHandler()
_logger.addHandler(handler)
getattr(_logger, type)(message.rstrip(), *args, **kwargs)
if have_wsgiref:
class BaseRequestHandler(WSGIRequestHandler):
"""
Subclass of the normal request handler that thinks it is
threaded or something like that. The default wsgiref handler
has wrong information so we need this class.
"""
multithreaded = False
multiprocess = False
_handler_class = None
def get_handler(self):
handler = self._handler_class
if handler is None:
class handler(ServerHandler):
wsgi_multithread = self.multithreaded
wsgi_multiprocess = self.multiprocess
self._handler_class = handler
rv = handler(self.rfile, self.wfile, self.get_stderr(),
self.get_environ())
rv.request_handler = self
return rv
def handle(self):
self.raw_requestline = self.rfile.readline()
if self.parse_request():
self.get_handler().run(self.server.get_app())
def log_request(self, code='-', size='-'):
return
#~ _log('info', '%s -- [%s] %s %s',
#~ self.address_string(),
#~ self.requestline,
#~ code,
#~ size
#~ )
def log_error(self, format, *args):
_log('error', 'Error: %s', format % args)
def log_message(self, format, *args):
_log('info', format, args)
def address_string(self):
return self.client_address[0]
def make_server(host, port, app=None, threaded=False, processes=1,
request_handler=None):
"""Create a new wsgiref server that is either threaded, or forks
or just processes one request after another.
"""
if not have_wsgiref:
raise RuntimeError('All the Werkzeug serving features require '
'an installed wsgiref library.')
request_handler = request_handler or BaseRequestHandler
if threaded and processes > 1:
raise ValueError("cannot have a multithreaded and "
"multi process server.")
elif threaded:
class request_handler(request_handler):
multithreaded = True
class server(ThreadingMixIn, WSGIServer):
pass
elif processes > 1:
class request_handler(request_handler):
multiprocess = True
class server(ForkingMixIn, WSGIServer):
max_children = processes - 1
else:
server = WSGIServer
srv = server((host, port), request_handler)
srv.set_app(app)
return srv
def reloader_loop(extra_files=None, interval=1):
"""When this function is run from the main thread, it will force other
threads to exit when any modules currently loaded change.
Copyright notice. This function is based on the autoreload.py from
the CherryPy trac which originated from WSGIKit which is now dead.
:param extra_files: a list of additional files it should watch.
"""
def iter_module_files():
for module in sys.modules.values():
filename = getattr(module, '__file__', None)
if filename:
while not os.path.isfile(filename):
filename = os.path.dirname(filename)
if not filename:
break
else:
if filename[-4:] in ('.pyc', '.pyo'):
filename = filename[:-1]
yield filename
mtimes = {}
while 1:
for filename in chain(iter_module_files(), extra_files or ()):
try:
mtime = os.stat(filename).st_mtime
except OSError:
continue
old_time = mtimes.get(filename)
if old_time is None:
mtimes[filename] = mtime
continue
elif mtime > old_time:
_log('info', ' * Detected change in %r, reloading' % filename)
sys.exit(3)
time.sleep(interval)
def restart_with_reloader():
"""Spawn a new Python interpreter with the same arguments as this one,
but running the reloader thread.
"""
while 1:
_log('info', ' * Restarting with reloader...')
args = [sys.executable] + sys.argv
if sys.platform == 'win32':
args = ['"%s"' % arg for arg in args]
new_environ = os.environ.copy()
new_environ['WERKZEUG_RUN_MAIN'] = 'true'
exit_code = os.spawnve(os.P_WAIT, sys.executable, args, new_environ)
if exit_code != 3:
return exit_code
def run_with_reloader(main_func, extra_files=None, interval=1):
"""Run the given function in an independent python interpreter."""
if os.environ.get('WERKZEUG_RUN_MAIN') == 'true':
thread.start_new_thread(main_func, ())
try:
reloader_loop(extra_files, interval)
except KeyboardInterrupt:
return
try:
sys.exit(restart_with_reloader())
except KeyboardInterrupt:
pass
def run_simple(hostname, port, application, use_reloader=False,
use_debugger=False, use_evalex=True,
extra_files=None, reloader_interval=1, threaded=False,
processes=1, request_handler=None):
"""Start an application using wsgiref and with an optional reloader. This
wraps `wsgiref` to fix the wrong default reporting of the multithreaded
WSGI variable and adds optional multithreading and fork support.
:param hostname: The host for the application. eg: ``'localhost'``
:param port: The port for the server. eg: ``8080``
:param application: the WSGI application to execute
:param use_reloader: should the server automatically restart the python
process if modules were changed?
:param use_debugger: should the werkzeug debugging system be used?
:param use_evalex: should the exception evaluation feature be enabled?
:param extra_files: a list of files the reloader should listen for
additionally to the modules. For example configuration
files.
:param reloader_interval: the interval for the reloader in seconds.
:param threaded: should the process handle each request in a separate
thread?
:param processes: number of processes to spawn.
:param request_handler: optional parameter that can be used to replace
the default wsgiref request handler. Have a look
at the `werkzeug.serving` sourcecode for more
details.
"""
if use_debugger:
from werkzeug.debug import DebuggedApplication
application = DebuggedApplication(application, use_evalex)
def inner():
srv = make_server(hostname, port, application, threaded,
processes, request_handler)
try:
srv.serve_forever()
except KeyboardInterrupt:
pass
if os.environ.get('WERKZEUG_RUN_MAIN') != 'true':
display_hostname = hostname or '127.0.0.1'
_log('info', ' * Running on http://%s:%d/', display_hostname, port)
if use_reloader:
# Create and destroy a socket so that any exceptions are raised before
# we spawn a separate Python interpreter and loose this ability.
test_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
test_socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
test_socket.bind((hostname, port))
test_socket.close()
run_with_reloader(inner, extra_files, reloader_interval)
else:
inner()
from wsgi_app import *
PORT = 8000
print 'Start server. Go to: http://localhost:%d/' % PORT
run_simple('localhost', PORT, application, use_reloader=True)