I have spent ages trying to figure this out. I'm basically trying to develop a website where I have to execute a python script when the users clicks a specific button. After researching on Stack Overflow and Google, I need to configure Apache to be able to run CGI scripts. I have seen numerous examples of software that can accomplish this, such as mod_wsgi. The problem is that I get extremely confused with the instructions for these softwares, especially for mod_wsgi. I don't understand the instructions at all, and I can't install the software and get anything to work.
If anyone has a very easy method for executing python scripts in Apache, I would greatly appreciate. If anyone would like to explain how to use mod_wsgi, I would greatly appreciate that as well, because as of right now I have no idea how to use it and the installation instructions are confusing the hell out of me.
One way, not so easy but simple in some way, is to use CGI, as you said.
You can find more information on Apache documentation and Python CGI module documentation.
But, basically, you have to set your server to run cgi sripts. This is done by editing httpd.conf or a .htaccess file:
For the first option, add or uncomment the follow:
LoadModule cgi_module modules/mod_cgi.so
ScriptAlias /cgi-bin/ /usr/local/apache2/cgi-bin/ # update the second location according to your configuration. It has to be a place where apache is allow to use, otherwise see apache documentation for setting another directory.
Then, you just need to add your python script in the directory that you set above.
Note that the output from your script must be preceded by a mime-type header, as Apache documentation says.
So, a hello world script could be named hello.py and its content could be:
#!/usr/bin/python
print('Content-type: text/html') # the mime-type header.
print() # header must be separated from body by 1 empty line.
print('Hello world')
Than, you can call your scrit from a browser:
http://localhost/cgi-bin/hello.py
Note that Python has some goodies inside its cgi realted builtin modules. The cgi module will give you a way to handle forms, and cgitb will give you a helpful (but not perfect) way to debug your script. For more on that, read the documentation again.
Finally, using cgi directly to run python scripts gives you a raw way to work with http requests. There is a lot of already done frameworks, like flask and django, that gives you more power easily. You could check that.
Related
I would like to run a couple of very simple Python 3 scripts on the web. As an example, say, the script just reads certain parameters from the URL, sends an email and prints out a simple HTML page saying "success".
I have a virtual private server with Nginx, so I am free to setup the best framework.
My question is: what is the state-of-the-art setup to do this?
More particularly: what do I need to install on my server for Nginx and what do I use in my Python scripts for e.g. reading the URL content? My idea is, that once the server setup is done, I can just put any new script_xy.py file into some directory and it can be accessed using the URL of the script, without a full blown deployment for each script.
Flask If I were to use Flask (or Django), each new script would need its own, continuously running process and its own Nginx setup. That seems like a total overkill to me. Another alternative is web2py, is it the same here or would that be an idea?
CGI 20 years ago I used to program such simple things as Perl scripts using CGI. I read this can be done in principle with Python, but CGI is slow. Then there is Fast CGI. However, my impression was that this is still a bit outdated?
WSGI WSGI seems to be the state-of-the-art alternative to CGI for Python. What python modules would I need to import in my script and what would be the setup for Nginx?
Something else? As you see, I might just need a few hints on what to search for. I am not even sure if I need to search for "Python web framework" or "Python server" etc.
Any help is greatly appreciated.
Thanks a lot for your ideas!
juxeku
I have a server side Python script that imports a big package called nltk. It ran at a command prompt, but would not run in Apache server.
I tried the logging and put it as the first import and created a log file immediately after. But nothing is written to the file before the script crashes.
Is there a way to see the "ImportError: no module ..." when the script runs on Apache?
As far as I'm aware, there's no built-in way to tell Apache to simply dump error log messages directly to the browser. I'm betting the error_log output happens in an independent part of the Apache pipeline -- just a guess.
Most of the time when someone wants output errors directly to the browser, that person is a developer working in a web script such as PHP, Python, Perl, or other lang. In order to output error messages that occur within your lang interpretter, you have to format the output and pass it through apache as if it was normal output.
PHP
Some languages provide an easy way to do this, such as the well known error_reporting switch in PHP.
Python
Unfortunately some languages, make this painful or almost impossible and Python is one of them.
At one time this was apparently possible using https://docs.python.org/3/library/cgitb.html
However that library has been deprecated. Seems like the Python community doesn't have much love for developers who want to get immediate feedback about errors in the browser. :(
I'm trying to set up an Ubuntu LAMP server. The machine would be dedicated to one site, and the site has a few .py files I'm working on. It would seem I have the PHP and MySQL up and running, but the Apache doesn't seem to be executing the .py files (just downloading them).
I then noticed that there seem to be two Interpreters, one at /usr/bin/python and one at /usr/local/bin/python
Which one should my headers be pointing to? At the moment I have !#usr/local/bin/python
I note that I also could have a problem with apache2.conf, but I'm not so sure. Using a virtual host I added a cgi handler (and tried mod_python) with no luck. I could post up the whole vitrual host from apache2.conf of that would help.
I've chkmod +rwx *.py in the site folder. Perhaps I should split this into to two posts, but I think they might be related.
Thanks
You can let the environment decide, which should mean it'll execute using whatever executable is run when you run python in your shell:
#!/usr/bin/env python
# Code goes here
I had a similar issue when running fast-cgi and I was told there is no way to fix it: Files being served are stale / cached ; Python as fcgi + web.py + nginx without doing custom work. I was told to use the python method, which invokes a local "web server" to host the python page.
Even doing that, the files served are stale / cached. If I make edits to the files, save and refresh, the python web server is still serving the stale / cached file.
The only way to get it to serve the modified file is to kill (ctrl+c) the script, and then restart...this takes about 5 seconds every-time and seriously impedes my development workflow.
Ideally any change to the script would be reflected next time the page is requested from the web server.
EDIT
#Jordan: Thanks for the suggestions. I've tried #2, which yields the following error:
app = web.application(urls, globals(), web.reloader)
AttributeError: 'module' object has no attribute 'reloader'
Per the documentation here: http://webpy.org/tutorial2.en
I then tried suggestion #4,
web.config.debug = True
Both still cause 'stale' files to get served.
Understandably you want a simple, set it up once and never worry about it again, solution. But you might be making this problem more difficult than it needs to be.
I generally write applications for an apache/modwsgi/nginx stack. If I have a caching problem, I just restart apache and voila, my python files are re-interpreted. I don't remember the commands to restart apache on all of my different boxes (mac's, ubuntu, centos, etc), and I shouldn't need to.
That is what command line aliases are for...
A python application is interpreted before it is run, and when run on a webserver, it is run once and should be considered stateless. This is unlike javascript running in a browser, which can be considered to have state since it is a continually running VM. You can edit javascript while it is running and that is probably fine for most applications of the language.
In python you generally write the code, run it, and if that doesn't work you start over. You don't edit the code in real time. That means you are knowingly saving the source and changing contexts to run it.
I am betting that you are editing your source from a Graphical IDE instead of a command-line editor like vi or emacs (I might be wrong, and I'm not saying there is anything 'wrong' with that). I only write iOS applications using an IDE, everything else I stick to ViM. Why? Because then I am always on the command line, and I am not distracted by anything (animations, mouse pointers, notifications). I finish writing my code, i quickly type ':wq' (write and quit), and then quickly type 'restartweb' (actually i usually type 're' then <\tab> to auto-complete) which is my alias to whatever the command to restart apache is. Voila my python is reinterpreted.
My point is that you should probably keep it simple and use something like an alias to solve your problem. It might not be the coolest thing you could do. But it is what Ninja coders have been doing for the last 20 years to get work done fast and simple.
Now obviously I only suggested a solution for apache, and I have never used web.py before. But the same possible solution still applies. Make a bash script that goes in your project directory, call it something like restart.bash. In it put something like:
rm -r *.pyc
Which will recursively remove all compiled pyc files, forcing your app to reload. Then make an alias in your ~/.bashrc that runs that file
Something like:
alias restartproject="bash /full/path/to/restart.bash"
Magical, now you have a solution that works everywhere, regardless of which type of web server you choose to run your application from.
Edit:
Now you have a solution that works everywhere but on a Windows IIS server. And if you are trying to run python from Windows, you should probably Stahp! hugz
We are using virtualenv right? :) We want to keep our python nice and system-agnostic so we can sell it to anyone right? :) And you should really check out ViM and emacs if you don't use them... you will bang your head against the wall for a week getting used to it, then never want to touch a mouse again after that.
Right, so Python is a compiled language when run on a web server. It's outputting a .pyc file that's the compiled version. Your goal is to tell the web server that the .pyc file is out of date and is no longer valid.
You have a few options:
Delete the relevant .pyc file
For web.py, use the reloader middleware
Send it a HUP signal (I'm lazy and usually do killall -SIGHUP python). You can do this automatically with a file watching tool like watchdog (thanks barracel).
web.config.debug = True should be the default in your application
None of those options are working for you?
Can I use os.system() or subprocess.call() to execute a Python program on a webserver?
I mean can I write these functions in a .py script and run it from a web browser and expect the program to be executed?
Thanks a lot.
EDIT:
Sorry for all the confusion, I am giving you more background to my problem.
The reason I am trying to do is this.
I have a Python program that accepts an XML file and returns me TTF file.
I run that program in terminal like this:
ttx somefile.xml
After which it does all the work and generates a ttf file.
Now when I deploy this script as a module on web server. I use a to allow user to browse and select the XML file.
Then I read the file data to temporary file and then pass the file to the module script to be executed like this:
ttx.main([temp_filename])
Is this right way to do it? Because at this point, I don't get any error in the log or in browser. I get blank screen.
When this didn't work, I was going to try os.system or subprocess.call
You do not use os.system or subprocess.call to execute something as a cgi process.
Maybe you should read the Python cgi tutorial here:
http://www.cs.virginia.edu/~lab2q/
If you want your cgi process to communicate with another process on your local machine, you might want to look at "REST frameworks" for Python.
So long as your server is configured to run CGI scripts (Apache's documentation for that is here, for example), yes, you can execute a python script from a webserver. Simply make sure the script is in the appropriate cgi-bin/ directory and that the file has executable permission on the server.
With regards to your comments:
You can, if you really want, explicitly allow other folders on the server to run executable code. I don't know what server you're using, but on Apache this is done by setting Option +ExecCGI for the folder you want. Again, see the docs I linked to.
You need to give an absolute path with respect to the server. As an example, a site I develop has the layout: /public_html/cgi-bin/ When I want to access .cgi or .py files, the url for the site is something like http://chess.narnia.homeunix.com/cgi-bin/index.cgi. You can also set up re-directs to certain files if you want.
One way to pass parameters through your browser is to append them to the URL like an HTTP POST method. Here's a good example of doing that.
Is that what you were looking for with your question, or did you want to actually invoke the python script with os.system()?
Yes, I do it all the time. Import as you would do normally, stick your .py in your cgi-bin folder and make sure the server is capable of handling python.
Another option would be to simply create an application on Google's App Engine. That gives you oodles of resources and APIs for Python execution.
http://code.google.com/appengine
I've done it quite a bit in classic ASP on IIS 5 and above. I would have the ASP engine execute python code (instead of, e.g., vbscript (hearkening back to the old days, here)). Behind those asp pages would be python modules written in straight python that could be imported and could execute pretty much arbitrary code. As others have mentioned, the effective user needs to have execute permission on the thing you're trying to execute.