Forums

Tring to launch a web.py dynamic site

I use the web.py framework.

I'm unable to reproduce on PythonAnywhere what I can run on my PC.

It's a dynamic website: a app.py script pulls from another script (map.py) and loads the outcomes into html files. You enter new inputs into the html form and the loop starts over. Minimal html and styling, no CSS nor JS files. Here's the project's tree:

├── bin
│   ├── app.py
│   ├── app.pyc
│   ├── __init__.py
│   ├── __init__.pyc
├── gothonweb
│   ├── __init__.py
│   ├── __init__.pyc
│   ├── map.py
│   └── map.pyc
├── templates
│   ├── layout.html
│   └── show_room.html
├── README.md
├── sessions
│   └── d8ecfa649500f00f77ced9621426a0e334d30eed
└── setup.py

Normally, I run the project on Ubuntu 16.04 with Py -2.7.

As an entry point, I must be located above bin (in project/, not in project/bin/)

I first send the path with export PYTHONPATH=.. Then, I fire the project with python bin/app.py. It connects on map.py (GET, POST...). Inputs go/outcomes show into show_room.html. show_room.html is simply embedded into layout.html. Whatever is inputed in the html forms generates a new outcome... From what I understand, to replicate this procedure, I must code a little wsgi.py file. 'ex52' is the 'project':

import sys

path = 'home/ugoproto/ex52/' if path not in sys.path:
sys.path.append(path)

from bin import app application = app.wsgifunc()

I tried all sort of things in both app.py and wsgi.py , but not one of them is working... Here is the last error log entry:

Error running WSGI application
Traceback (most recent call last):
  File "/bin/user_wsgi_wrapper.py", line 154, in __call__
    app_iterator = self.app(environ, start_response)
  File "/bin/user_wsgi_wrapper.py", line 170, in import_error_application
    raise e
AttributeError: 'function' object has no attribute 'add_processor'

I need a hand on this. I'm sure, it some kind of stupid typo I can't spot, or a missing line. Here's the last app.py:

import web from gothonweb import map

urls = (
    '/game', 'GameEngine',
    '/', 'Index' )

app = web.application(urls, globals())

if web.config.get('_session') is None:
    store = web.session.DiskStore('sessions')
    session = web.session.Session(app, store,
                                  initializer={'room': None})
    web.config._session = session else:
    session = web.config._session

render = web.template.render('templates/', base="layout_plus") #
/templates/layout_plus.html

class Index(object):
    def GET(self):
        session.room = map.START
        web.seeother("/game")

class GameEngine(object):
    def GET(self):
        if session.room:
            return render.show_room_plus(room=session.room) # /templates/show_room_plus.html

    def POST(self):
        form = web.input(action=None)
        if (session.room.name == "Laser Weapon Armory") and (session.room.paths.has_key(form.action) == False):
            form.action = '*'
        if session.room and form.action: # if all true, execute the next line; otherwise, jump over it
            if session.room.paths.has_key(form.action): # if the entry is what is expected in the dictionary (excluding errors, mispelling,
no entry at all), execute the next line; otherwise, jump over it
                session.room = session.room.go(form.action)
        web.seeother("/game")

if __name__ == "__main__":
    app.run()

My guess is that the "web" you're importing from gothonweb is not actually from the web.py module, but from something else. Have a look in the gothonweb module to ensure that the web that is defined there is actually web.py and not something else.

Glenn,

OK, the word 'gothonweb' might be confusing.

I changed the name of the dir to 'gothonmap/'.

However, the engine running web.py is app.py. The module import web.

gothonmap/map.py is a content file. If we oversimplify the situation, map.py is a dictionary. app.py pulls content (value) from map.py and then shows the outcomes (value) in html files in templates/, offering other choices (new keys). You enter one of the choice (key), and the loop starts over: pulling out new content (value).

This structure runs on a PC. What is missing to emulate it online?

An image is worth a thousand words. If I could only send you a little recording (light for emails), it would explain how it goes locally. Now, if we could plug the right cable in the right outlet...

Ah! I think I see it. You're doing from bin import app in your wsgi file which imports the app module from bin, but your actual application is a variable that is in that module (also called app) Change the import in your wsgi file to be from bin.app import app and I think it will work.

Yes, somehow, it worked. We are close... I get a status webpage with 200 OK.

But I can't see the opening webpage. And this why... I would get the same error while trying to run the package on my PC. Locally, after starting the script, you must load the webpage at the root: http://0.0.0.0:8080/ because of urls = ( '/game', 'GameEngine', '/', 'Index') in the app.py file. But we start at /game, as the error page suggests: <type 'exceptions.AttributeError'> at /game; so, there are No template named show_room_plus...

The root, or /, is associated with Index. Only after you make your first choice, the package will move on to /game to interrogate the GameEngine or the map (pull (GET) the content into the web page depending on the choice you entered (POST)).

We must find a way to make sure we start at the root, not at /game. On my PC, I can do it manually. I type in http://0.0.0.0:8080/. How can we ensure that online? I have never deployed online, so it is beyond what I know, but I'm eager to learn how.

OK, got it.! The wsgi file does its job. The problem was now on my side; the code I was feeding P.A. with. I fixed the little bugs in the python and html files.

Case settled. Cheers.

Excellent, thanks for letting us know!