BottlePy App and CherryPy server not logging access - python

I'm serving a BottlePy App with CherryPy like this:
import cherrypy
from myapp import MyApp
from beaker.middleware import SessionMiddleware
appdir = '/path/to/app'
app = MyApp(appdir)
session_opts = {
'session.timeout': 600, # 10 minutes
'session.type': 'file',
'session.auto': True,
'session.data_dir': appdir + '/auth/data'
}
app = SessionMiddleware(app, session_opts)
cherrypy.tree.graft(app, '/')
cherrypy.config.update({
'log.screen': False,
'log.access_file': appdir + '/front_end/cherrypy.access.log',
'log.error_file': appdir + '/front_end/cherrypy.error.log',
'server.socket_port': 8080,
'server.socket_host': '0.0.0.0'
})
cherrypy.engine.start()
cherrypy.engine.block()
Everything seems to be working properly, but cherrypy.access.log remains totally empty, while cherrypy.error.log reads:
[30/Dec/2014:11:04:55] ENGINE Bus STARTING
[30/Dec/2014:11:04:55] ENGINE Started monitor thread '_TimeoutMonitor'.
[30/Dec/2014:11:04:55] ENGINE Started monitor thread 'Autoreloader'.
[30/Dec/2014:11:04:56] ENGINE Serving on http://0.0.0.0:8080
[30/Dec/2014:11:04:56] ENGINE Bus STARTED
But nothing else, no access logs, even after serving content.
I also tried
from cherrypy import wsgiserver
# Instead of the cherrypy.* calls
server = wsgiserver.CherryPyWSGIServer(('0.0.0.0', 8080), app)
server.start()
but it will print the same as above, but no access logs. Could not find any further documentation on logging and BottlePy integration.

The app you're running is not native CherryPy one, and grafting basically bypasses most of CP's internals, most likely including access logging.
Since you don't use any CherryPy's features besides basic WSGI publishing, you may be better off using one of the more serving-oriented (and more recent) solutions like uWSGI, Gunicorn or nginx/Apache+plugins.

You need to set log.screen to True to enable both error and access logs.
See (old) docs: https://cherrypy.readthedocs.org/en/3.3.0/refman/_cplogging.html

Related

Docker and WSGI with a Python Pyramid app?

I am looking at two articles on how to Dockerize a Pyramid app. I am not that familiar with Python, but I am fairly certain with a Pyramid app you need to use WSGI.
This article uses WSGI:
https://medium.com/#greut/minimal-python-deployment-on-docker-with-uwsgi-bc5aa89b3d35
This one just runs the python executable directly:
https://runnable.com/docker/python/dockerize-your-pyramid-application
It seems unlikely to me that you can run python directly and not incorporate WSGI, can anyone provide an explanation for why the runnable.com article's docker solution would work?
Per the scripts in the second link:
from wsgiref.simple_server import make_server
from pyramid.config import Configurator
from pyramid.response import Response
~snip~
if __name__ == '__main__':
config = Configurator()
config.add_route('hello', '/')
config.add_view(hello_world, route_name='hello')
app = config.make_wsgi_app() # The wsgi server is configured here
server = make_server('0.0.0.0', 6543, app) # and here
This contains an explanation of why the wsgi server is built in the if __name__=="__main__" block

Flask with gevent multicore

What is the clear way to run flask application with gevent backend server and utilize all processor cores? I have idea to run multiple copies of flask application where gevent WSGIServer listen one port in diapason 5000..5003 (for 4 processes) and nginx as load balancer.
But I'm not sure that this way is the best and may be there are some other ways to do it. For example, master process listen one port and workers process incoming connections.
I'll take a shot!
Nginx!
server section:
location / {
include proxy_params;
proxy_pass http://127.0.0.1:5000;
}
Flask App
This is a simple flask app that i will be using for this example.
myapp.py:
from flask import Flask
app = Flask(__name__)
#app.route("/")
def hello():
return "Hello World!"
if __name__ == "__main__":
app.run()
uWSGI
Okay so I know that you said that you wanted to use gevent, but if you are willing to compromise on that a little bit I think you would be very happy with this setup.
[uwsgi]
master = true
plugin = python
http-socket = 127.0.0.1:5000
workers = 4
wsgi-file = myapp.py
callable = app
Gunicorn
If you must have gevent you might like this little setup
config.py:
import multiprocessing
workers = multiprocessing.cpu_count()
bind = "127.0.0.1:5000"
worker_class = 'gevent'
worker_connections = 30
Then you can run:
gunicorn -c config.py myapp:app
Thats right you have a worker for each cpu and 30 connections per worker.
See if that works for you.
If you are really sold on using nginx as a load balancer try something like this in your http section
upstream backend {
server 127.0.0.1:5000;
server 127.0.0.1:5002;
server 127.0.0.1:5003;
server 127.0.0.1:5004;
}
then one of these in the server section
location / {
include proxy_params;
proxy_pass http://backend;
}
Good Luck buddy!

Serve a Flask app on a sub-url during localhost development

I have a Flask app as backend that serves a REST API and an AngularJS front-end app.
I use Grunt/Livereload to serve the front-end at the address: http://localhost:5000/
Is it possible to serve the Flask app on a sub-url of localhost during development, using app.run() or run_simple from werkzeug?
Specifically I would like to have the Flask app accessible at the address: http://localhost:5000/api
I found this solution but it has the disadvantage of serving a dummy app at http://localhost:5000/ which uses the address and doesn't let me serve the AngularJS app at that address.
The way that Flask and Yoman are set up you cannot actually do this - it is possible to have two processes share the same port, but it is generally done to allow one master process to pass off handling of individual requests to sub-processes, which is not quite what you are doing here. (In general, in production, you would run both the front and back end behind a proxy server like nginx.)
Fortunately, you do not have to re-invent the wheel or run a separate proxy server just to develop your app - there is a Grunt plugin called grunt-connect-proxy that will let you proxy requests to a sub-url to another location entirely. That will let you spin up your Flask backend server on a different port (say port 5001) and proxy requests to localhost:5000/api (for example) to localhost:5001/:
connect: {
options: {
port: 5000,
hostname: 'localhost'
},
proxies: [
{
context: '/api',
host: '127.0.0.1',
port: 5001,
https: false,
changeOrigin: false,
xforward: false
}
]
}
And then you can run your Flask app with app.run(port=5001).
This worked for me
from flask import Flask
prefix = '/abc'
app = Flask(__name__)
# redefine route
def route(path, *args, **kwargs):
return _route(prefix + path, *args, **kwargs)
_route = app.route
app.route = route
# Test function
#app.route('/')
def hello_world():
return 'Hello World!'
if __name__ == '__main__':
app.run()

Tornado web server in webfaction

I am starting with web development. I am trying to develop and webapp using the Instagram API and Django. I was looking that a lot of people it's using Tornado Web Server for Real Time Subscriptions. So I am using Webfaction as a host and found this code so I can wrap my Django project with the "WSGI Container" that Tornado Web Server provides:
import os
import tornado.httpserver
import tornado.ioloop
import tornado.wsgi
import tornado.web
import sys
import django.core.handlers.wsgi
sys.path.append('/path/to/project')
class HelloHandler(tornado.web.RequestHandler):
def get(self):
self.write('Hello from tornado')
def main():
os.environ['DJANGO_SETTINGS_MODULE'] = 'myproject.settings' # path to your settings module
wsgi_app = tornado.wsgi.WSGIContainer(django.core.handlers.wsgi.WSGIHandler())
tornado_app = tornado.web.Application(
[
('/hello-tornado', HelloHandler),
('.*', tornado.web.FallbackHandler, dict(fallback=wsgi_app)),
]
)
http_server = tornado.httpserver.HTTPServer(tornado_app)
http_server.listen(8080)
tornado.ioloop.IOLoop.instance().start()
if __name__ == "__main__":
main()
So I run this python script inside my Webfaction server and everytime I try to access "http://mywebsite.com/hello-tornado/" does not seem to work. I know I am running that Tornado web server on that port but do not know how too access from the browser or something like that. What I am doing wrong here? Thanks for your help and patience. Will cyber high-five for every answer.
EDIT: What I am really trying to do is that I want to receive all the calls from the subscriptions that I make with the Instagram RealTime Subscription API through Tornado, for that I have a callback url "http://mysite.com/sub" and I want to be able to receive through Tornado.
You are starting the server at port 8080, Web browsers use port 80 by default, try using: http://mywebsite.com:8080/hello-tornado
if you want to use port 80 and you already have a web server running in the box you can try following Ali-Akber Saifee suggestion, or run the WSGI application directly from the server, using something like mod_python (http://www.modpython.org), you will lose the ability to run Tornado code, but Django will work.
You have to create a custom app (listening on port), note the port that is assigned to your app then configure tornado to serve on that port: http_server.listen(my port)
You can also avoid tornado and start directly by installing a django app.

Running a Pyramid WSGI application under tornado

Pyramid uses it's own Waitress web server for development purposes, but I want to serve my WSGI app under Tornado. I think I should configure it using the pserve .ini files, but I can't get it to work
The Pyramid application can be loaded from the INI files easily. From there you just pass the wsgi app into Tornado's WSGIContainer.
from pyramid.paster import get_app
app = get_app('development.ini')
container = tornado.wsgi.WSGIContainer(app)
Again, not really recommending running WSGI under Tornado, since it gives you none of the advantages of Tornado.
Should you still want to do it for some reason, the second example of the docs seems to be what you are looking for: http://www.tornadoweb.org/documentation/wsgi.html
def simple_app(environ, start_response):
status = "200 OK"
response_headers = [("Content-type", "text/plain")]
start_response(status, response_headers)
return ["Hello world!\n"]
container = tornado.wsgi.WSGIContainer(simple_app)
http_server = tornado.httpserver.HTTPServer(container)
http_server.listen(8888)
tornado.ioloop.IOLoop.instance().start()

Categories

Resources