Python , modwsgi et bottle: trucs et astuces ============================================ Gestion de log -------------- Il est toujours possible de créer un logger pour écrire dans un fichier externe les logs applicatives. .. code-block:: python import os, platform import logging if platform.platform().startswith('Windows'): logging_file = os.path.join(os.getenv('HOMEDRIVE'), os.getenv('HOMEPATH'), 'test.log') else: logging_file = os.path.join(os.getenv('HOME'), 'test.log') print("Logging to", logging_file) logging.basicConfig(level=logging.DEBUG, format='%(asctime)s : %(levelname)s - %(name)s - %(module)s \ %(funcName)s : %(message)s', filename = logging_file, filemode = 'w', ) logging.debug("Start of the program") logging.info("Doing something") logging.warning("Dying now") Mais il est aussi possible d'écrire dans les logs apache du site web. Cependant cela ce limite à: - des messages d'erreurs - uniquement dans le contexte request .. code-block:: python @route('/') def index(): print >> request.environ['wsgi.errors'], 'hello' print >> request.environ['wsgi.errors'], '\n'.join(('%s:%s' % (i,request.environ[i]) for i in request.environ.keys())) return static_file('index.html', root='C:/www/test1') ce qui donne :: [Sun May 26 21:31:31 2013] [error] [client 127.0.0.1] hello [Sun May 26 21:31:31 2013] [error] [client 127.0.0.1] wsgi.multiprocess:False [Sun May 26 21:31:31 2013] [error] [client 127.0.0.1] SERVER_PROTOCOL:HTTP/1.1 [Sun May 26 21:31:31 2013] [error] [client 127.0.0.1] SERVER_SOFTWARE:Apache/2.2.22 (Win32) mod_wsgi/3.3 Python/2.7.2 [Sun May 26 21:31:31 2013] [error] [client 127.0.0.1] SCRIPT_NAME:/myapp [Sun May 26 21:31:31 2013] [error] [client 127.0.0.1] mod_wsgi.handler_script: [Sun May 26 21:31:31 2013] [error] [client 127.0.0.1] SERVER_SIGNATURE: [Sun May 26 21:31:31 2013] [error] [client 127.0.0.1] REQUEST_METHOD:GET [Sun May 26 21:31:31 2013] [error] [client 127.0.0.1] PATH_INFO: [Sun May 26 21:31:31 2013] [error] [client 127.0.0.1] PATHEXT:.COM;.EXE;.BAT;.CMD;.VBS;.VBE;.JS;.JSE;.WSF;.WSH;.MSC [Sun May 26 21:31:31 2013] [error] [client 127.0.0.1] QUERY_STRING: [Sun May 26 21:31:31 2013] [error] [client 127.0.0.1] bottle.app: [Sun May 26 21:31:31 2013] [error] [client 127.0.0.1] HTTP_USER_AGENT:Mozilla/5.0 (Windows NT 6.1; rv:21.0) Gecko/20100101 Firefox/21.0 [Sun May 26 21:31:31 2013] [error] [client 127.0.0.1] HTTP_CONNECTION:keep-alive [Sun May 26 21:31:31 2013] [error] [client 127.0.0.1] SERVER_NAME:127.0.0.1 [Sun May 26 21:31:31 2013] [error] [client 127.0.0.1] REMOTE_ADDR:127.0.0.1 [Sun May 26 21:31:31 2013] [error] [client 127.0.0.1] mod_wsgi.request_handler:wsgi-script [Sun May 26 21:31:31 2013] [error] [client 127.0.0.1] wsgi.url_scheme:http [Sun May 26 21:31:31 2013] [error] [client 127.0.0.1] bottle.request: [Sun May 26 21:31:31 2013] [error] [client 127.0.0.1] mod_wsgi.callable_object:application [Sun May 26 21:31:31 2013] [error] [client 127.0.0.1] SERVER_PORT:80 [Sun May 26 21:31:31 2013] [error] [client 127.0.0.1] mod_wsgi.version:(3, 3) [Sun May 26 21:31:31 2013] [error] [client 127.0.0.1] mod_wsgi.input_chunked:0 [Sun May 26 21:31:31 2013] [error] [client 127.0.0.1] SERVER_ADDR:127.0.0.1 [Sun May 26 21:31:31 2013] [error] [client 127.0.0.1] DOCUMENT_ROOT:C:/www/test1 [Sun May 26 21:31:31 2013] [error] [client 127.0.0.1] mod_wsgi.process_group: [Sun May 26 21:31:31 2013] [error] [client 127.0.0.1] COMSPEC:C:\\Windows\\system32\\cmd.exe [Sun May 26 21:31:31 2013] [error] [client 127.0.0.1] route.handle:> [Sun May 26 21:31:31 2013] [error] [client 127.0.0.1] SCRIPT_FILENAME:C:/www/test1/wsgi-scripts/myapp.wsgi [Sun May 26 21:31:31 2013] [error] [client 127.0.0.1] SERVER_ADMIN:admin@fraoustin-PC.home [Sun May 26 21:31:31 2013] [error] [client 127.0.0.1] route.url_args:{} [Sun May 26 21:31:31 2013] [error] [client 127.0.0.1] wsgi.input: [Sun May 26 21:31:31 2013] [error] [client 127.0.0.1] HTTP_HOST:127.0.0.1 [Sun May 26 21:31:31 2013] [error] [client 127.0.0.1] wsgi.multithread:True [Sun May 26 21:31:31 2013] [error] [client 127.0.0.1] SystemRoot:C:\\Windows [Sun May 26 21:31:31 2013] [error] [client 127.0.0.1] REQUEST_URI:/myapp [Sun May 26 21:31:31 2013] [error] [client 127.0.0.1] HTTP_ACCEPT:text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8 [Sun May 26 21:31:31 2013] [error] [client 127.0.0.1] WINDIR:C:\\Windows [Sun May 26 21:31:31 2013] [error] [client 127.0.0.1] wsgi.version:(1, 1) [Sun May 26 21:31:31 2013] [error] [client 127.0.0.1] bottle.route:> [Sun May 26 21:31:31 2013] [error] [client 127.0.0.1] GATEWAY_INTERFACE:CGI/1.1 [Sun May 26 21:31:31 2013] [error] [client 127.0.0.1] wsgi.run_once:False [Sun May 26 21:31:31 2013] [error] [client 127.0.0.1] wsgi.errors: [Sun May 26 21:31:31 2013] [error] [client 127.0.0.1] REMOTE_PORT:56249 [Sun May 26 21:31:31 2013] [error] [client 127.0.0.1] HTTP_ACCEPT_LANGUAGE:fr,fr-fr;q=0.8,en-us;q=0.5,en;q=0.3 [Sun May 26 21:31:31 2013] [error] [client 127.0.0.1] mod_wsgi.application_group:test1.fr|/myapp [Sun May 26 21:31:31 2013] [error] [client 127.0.0.1] mod_wsgi.script_reloading:1 [Sun May 26 21:31:31 2013] [error] [client 127.0.0.1] wsgi.file_wrapper: [Sun May 26 21:31:31 2013] [error] [client 127.0.0.1] HTTP_ACCEPT_ENCODING:gzip, deflate Gestion d'un pool de connexion ------------------------------ Il est souvent utile d'utiliser des pools de connexion pour le lien avec un SGBD. On peut utiliser pour cela le module *Queue* de python .. code-block:: python # Change working directory so relative paths (and template lookup) work again import os, sys os.chdir(os.path.dirname(__file__)) sys.path.append(os.path.dirname(__file__)) #permet l'utilisation de pypyodbc import bottle from bottle import route, run, template, static_file, request, response import time from xml.dom.minidom import getDOMImplementation import Queue import pypyodbc as odbc CNX_STR='DSN=TESTPG;UID=postgres;PWD=postgres' SQL='select count(*) from test' SIZE_POOL=10 class PoolConnect(Queue.Queue): def put(self, item, block=True, timeout=None): item.commit() Queue.Queue.put(self, item, block, timeout) POOL = PoolConnect(maxsize=SIZE_POOL) for i in range(0,SIZE_POOL): POOL.put(odbc.connect(CNX_STR)) def generate_response(value): impl = getDOMImplementation() newdoc = impl.createDocument(None,"sample",None) top_element = newdoc.documentElement att = newdoc.createElement('msg') txt = newdoc.createTextNode(str(value)) att.appendChild(txt) top_element.appendChild(att) return newdoc.toxml('iso-8859-15') @route('/') def index(): return static_file('index.html', root='C:/www/test1') @route('/bypool') def bypool(): a = POOL.get() cursor = a.cursor() cursor.execute(SQL) row = cursor.fetchone() POOL.put(a) response.headers['Content-Type'] = 'text/xml' return generate_response(row[0]) application = bottle.default_app()