I have a Python application that interfaces with a licensed Windows-based program, and I need to provide a web-based interface (using GET/POST requests) for this Python application. I am using IIS as the web server for this interface, because we already have web-based interfaces for other applications working through IIS.
In order to use this licensed Windows-based program, each instance must make a very resource intensive license check call, which then grants the license. Once the instance is done, I must make a very resource intensive license release call, which then releases the license back into the pool. In order to improve the speed of web application, I desire to only make each of these calls once: once when the web server starts (granting the license), and once when the server stops (releasing the license).
Based on my reading, I came to the conclusion that using a FastCGI (this may be wrong) would address the general design need of having a single-thread application within which I would maintain my license grant (as opposed to CGI, which would require the grant and release for every request). My application is very simple, so I selected Bottle as the framework to build my application. And I'm using wfastcgi to use Python WSGI with IIS.
In order to get the start/stop code working, I have created the following web.config
and app.py
files:
web.config
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<appSettings>
<add key="WSGI_HANDLER" value="app.wsgi_app()"/>
<add key="PYTHONPATH" value="C:\web\App"/>
<add key="WSGI_LOG" value="C:\web\App\wfastcgi.log"/>
</appSettings>
<system.webServer>
<handlers>
<add name="PythonHandler" path="*" verb="*" modules="FastCgiModule" scriptProcessor="C:\python\Python37\python.exe|C:\python\Python37\lib\site-packages\wfastcgi.py" resourceType="Unspecified" requireAccess="Script"/>
</handlers>
</system.webServer>
</configuration>
app.py
from bottle import default_app, route
import atexit
import myapp
mylicense = None
def wsgi_app():
global mylicense
mylicense = myapp.get_license()
return default_app()
@route('/app/<page>')
def mypage(page):
return myapp.get_data(mylicense,page)
@atexit.register
def close_server():
myapp.release_license(mylicense)
As far as I can tell, this works. However, I feel like my solution is kludgy to the extreme. I would assume that there is some clean way to register startup/shutdown code for WSGI. I also feel like my use of the global mylicense
variable is terrible, and that I should be able to pass the license object into my route functions much more cleanly as well.
Can anyone suggest how I can do these better/cleaner/faster/stronger?