Forums

Error while shifting Bottle App from localhost

I am developing a Python bottle web API. It was working fine on localhost/8080 but after shifting it to Pythonanywhere, it's not working and giving this error. How to resolve it?

2014-09-21 12:58:33,954 :/usr/lib/python2.7/threading.py:1158: RuntimeWarning: tp_compare didn't return -1 or -2 for exception
2014-09-21 12:58:33,955 :  return _active[_get_ident()]
2014-09-21 12:58:33,955 :Traceback (most recent call last):
2014-09-21 12:58:33,955 :  File "/bin/user_wsgi_wrapper.py", line 123, in __call__
2014-09-21 12:58:33,955 :    self.error_log_file.logger.exception("Error running WSGI application")
2014-09-21 12:58:33,955 :  File "/usr/lib/python2.7/logging/__init__.py", line 1183, in exception
2014-09-21 12:58:33,955 :    self.error(msg, *args, **kwargs)
2014-09-21 12:58:33,955 :  File "/usr/lib/python2.7/logging/__init__.py", line 1176, in error
2014-09-21 12:58:33,956 :    self._log(ERROR, msg, args, **kwargs)
2014-09-21 12:58:33,956 :  File "/usr/lib/python2.7/logging/__init__.py", line 1268, in _log
2014-09-21 12:58:33,956 :    record = self.makeRecord(self.name, level, fn, lno, msg, args, exc_info, func, extra)
2014-09-21 12:58:33,956 :  File "/usr/lib/python2.7/logging/__init__.py", line 1242, in makeRecord
2014-09-21 12:58:33,956 :    rv = LogRecord(name, level, fn, lno, msg, args, exc_info, func)
2014-09-21 12:58:33,956 :  File "/usr/lib/python2.7/logging/__init__.py", line 284, in __init__
2014-09-21 12:58:33,956 :    self.threadName = threading.current_thread().name
2014-09-21 12:58:33,957 :  File "/usr/lib/python2.7/threading.py", line 1158, in currentThread
2014-09-21 12:58:33,957 :    return _active[_get_ident()]
2014-09-21 12:58:33,957 :  File "/bin/user_wsgi_wrapper.py", line 115, in __call__
2014-09-21 12:58:33,957 :    app_iterator = self.app(environ, start_response)
2014-09-21 12:58:33,957 :  File "/bin/user_wsgi_wrapper.py", line 129, in import_error_application
2014-09-21 12:58:33,957 :    raise e
2014-09-21 12:58:33,957 :OSError: [Errno 2] No such file or directory

Can I take a look at your files? (We can see them from our side, but our policy is always ask to permission first so that you have as much privacy as possible.)

Yes. That's so honest of you. Please see the files and suggest me the possible cause.

Thanks! So, I can see one thing that might be causing problems: at the end of your file bottle_app.py you have this:

run(host='0.0.0.0', port=80)

That's perfectly correct when you're running a test server locally, but when it's deployed to a live environment like PythonAnywhere, you shouldn't call run because it will stop the app from connecting to the web-serving infrastructure. If you replace it with the following code, then you'll have something that will work in both the test server and PythonAnywhere:

if __name__ == "__main__":
    run(host='0.0.0.0', port=80)

Give that a go, and reload your app from the "Web" tab, and let me know if you have any further problems.

I get this error now:

Traceback (most recent call last):                                                                                                                                                             
  File "/home/sahildua2305/mysite/bottle_app.py", line 8, in <module>                                                                                                                          
    run(host='0.0.0.0', port=80)                                                                                                                                                               
  File "/usr/local/lib/python2.7/dist-packages/bottle.py", line 2703, in run                                                                                                                   
    server.run(app)                                                                                                                                                                            
  File "/usr/local/lib/python2.7/dist-packages/bottle.py", line 2385, in run                                                                                                                   
    srv = make_server(self.host, self.port, handler, **self.options)                                                                                                                           
  File "/usr/lib/python2.7/wsgiref/simple_server.py", line 144, in make_server                                                                                                                 
    server = server_class((host, port), handler_class)                                                                                                                                         
  File "/usr/lib/python2.7/SocketServer.py", line 419, in __init__                                                                                                                             
    self.server_bind()                                                                                                                                                                         
  File "/usr/lib/python2.7/wsgiref/simple_server.py", line 48, in server_bind                                                                                                                  
    HTTPServer.server_bind(self)                                                                                                                                                               
  File "/usr/lib/python2.7/BaseHTTPServer.py", line 108, in server_bind                                                                                                                        
    SocketServer.TCPServer.server_bind(self)                                                                                                                                                   
  File "/usr/lib/python2.7/SocketServer.py", line 430, in server_bind                                                                                                                          
    self.socket.bind(self.server_address)                                                                                                                                                      
  File "/usr/lib/python2.7/socket.py", line 224, in meth                                                                                                                                       
    return getattr(self._sock,name)(*args)                                                                                                                                                     
socket.error: [Errno 13] Permission denied

Have you reloaded the app? That error says that the run is still being executed.

Hmm, looking at your error logs, it looks like there's a different error now. At the bottom of the log file (which is where the most recent errors appear) it says this:

ImportError: cannot import name application

It looks like you need to add this to the bottom:

application = default_app()

...and also to import default_app from bottle at the top.

Made changes as you suggested. It runs without any error. But do I need to do "Save & Run" everytime? Can't bottle server be ON even when no one turns it on by running it?

I mean - I am creating a simple API out of this app(which should be running 24x7). People should be able to send http requests to a link and get back responses. How to run the server file so as to make it work like this?

By the way - [http://sahildua2305.pythonanywhere.com/] still gives an error.

You don't need to run it at all, once you've set it up from the "Web" tab then it's always up and running.

So the thing we need to solve is the error you're seeing at http://sahildua2305.pythonanywhere.com/. Because the error in your log file (linked from the "Web" tab) is still the same as it was before, I think you just need to hit the "Reload" button there and it will start working.

Thanks. I reloaded it, still the same error at http://sahildua2305.pythonanywhere.com/ . Please see what can be done with this. I am new to Bottle.

The problem is that you've put the line saying

application = default_app()

...inside the if statement you added earlier. The purpose of the if is to hide code that should not be run on PythonAnywhere, but should be run locally, like the run, but the setting of the application variable is for PythonAnywhere. Change the end of your code so that it looks like this:

application = default_app()

if __name__ == "__main__":
    run(host='0.0.0.0', port=80)

Yeah. Done with that.

Now I am facing general python problem. I am not able to use @route properly. What I want to do is - send a GET HTTP request to https://sahildua2305.pythonanywhere.com/expand with parameters - {url : "someurl.com/something"}

How to make it work this way?

From a quick look at your code, it looks like you're trying to expand the parameters after the "?" inside the route decorator's parameters, which won't work.

route is how you define URLs on your site. The stuff after the "?" doesn't count as part of the URL, it's parameters that you're passing to the thing that's running on that URL.

So you want a route decorator that looks like this:

@route('/expand')
def expand():

...and then inside the function, you get the parameters from the query dictionary like this:

    url = request.query['url']

You can read more about it on this Stack Overflow post.

I have changed it to @route('/expand')

Still when I send this request :

r = requests.get('http://sahildua2305.pythonanywhere.com/expand', params={'url':'http://tuq.in/myspeed'})

It gives 500 Internal error. Please see what could be the error..

HTTP request to /expand works, but when request is sent along with the parameter url, then it returns a 500 Internal error. How to let the bottle app know that I want to process the params along with /expand?

The 500 internal server error is saying that something is going wrong in your app. Have you taken a look at the error log (linked from the "Web" tab)?

This is the error I see now:

2014-09-24 18:50:24,930 :Traceback (most recent call last):
2014-09-24 18:50:24,933 :  File "/usr/local/lib/python2.7/dist-packages/bottle.py", line 764, in _handle
2014-09-24 18:50:24,933 :    return route.call(**args)
2014-09-24 18:50:24,933 :  File "/usr/local/lib/python2.7/dist-packages/bottle.py", line 1575, in wrapper
2014-09-24 18:50:24,933 :    rv = callback(*a, **ka)
2014-09-24 18:50:24,933 :  File "/home/sahildua2305/mysite/bottle_app.py", line 41, in expand
2014-09-24 18:50:24,933 :    url_list = expandURL(url)
2014-09-24 18:50:24,933 :  File "/home/sahildua2305/mysite/bottle_app.py", line 9, in expandURL
2014-09-24 18:50:24,933 :    return unshorten_me(url, urls)
2014-09-24 18:50:24,933 :  File "/home/sahildua2305/mysite/bottle_app.py", line 14, in unshorten_me
2014-09-24 18:50:24,933 :    h.request('HEAD', parsed.path)
2014-09-24 18:50:24,933 :  File "/usr/lib/python2.7/httplib.py", line 973, in request
2014-09-24 18:50:24,933 :    self._send_request(method, url, body, headers)
2014-09-24 18:50:24,934 :  File "/usr/lib/python2.7/httplib.py", line 1007, in _send_request
2014-09-24 18:50:24,934 :    self.endheaders(body)
2014-09-24 18:50:24,934 :  File "/usr/lib/python2.7/httplib.py", line 969, in endheaders
2014-09-24 18:50:24,934 :    self._send_output(message_body)
2014-09-24 18:50:24,934 :  File "/usr/lib/python2.7/httplib.py", line 829, in _send_output
2014-09-24 18:50:24,934 :    self.send(msg)
2014-09-24 18:50:24,934 :  File "/usr/lib/python2.7/httplib.py", line 791, in send
2014-09-24 18:50:24,934 :    self.connect()
2014-09-24 18:50:24,934 :  File "/usr/lib/python2.7/httplib.py", line 772, in connect
2014-09-24 18:50:24,934 :    self.timeout, self.source_address)
2014-09-24 18:50:24,934 :  File "/usr/lib/python2.7/socket.py", line 571, in create_connection
2014-09-24 18:50:24,934 :    raise err
2014-09-24 18:50:24,934 :error: [Errno 111] Connection refused

You're on a free account and it look like you're trying to connect to a URL. We don't allow unfiltered access to the internet from free accounts. We have a whitelist of sites that free accounts can access. If the site you're trying to use has an API and we think that it will be useful for other free users, we'll add it to the whitelist. Just send a request with a link to the API docs for the site.

No.No, looks like you are mis-understanding the case.

Actually, I am trying to develop an API where others can send HTTP requests and retrieve data. I don't need any website to be added to whitelist at all.

Please look into this. Thanks, for your time.

I may have, but this

2014-09-24 18:50:24,933 :  File "/home/sahildua2305/mysite/bottle_app.py", line 14, in unshorten_me
2014-09-24 18:50:24,933 :    h.request('HEAD', parsed.path)

looks like your web app trying to make a request to parsed.path. If parsed.path goes to a domain that is not on the whitelist, then you'll get Connection refused.

But what I am doing while making API call is simply a GET request to sahildua2305.pythonanywhere.com/expand with parameters - params={'url':'http://tuq.in/sahil'}

What might be the cause of this problem?

OK, I think there are two problems here.

Firstly, you're using httplib in your web app. That's a very basic HTTP library, and doesn't handle proxies. Free accounts on PythonAnywhere need to use a proxy to access the outside Internet, so you'd be better off using requests instead of httplib -- it does everything you want, it supports proxies transparently (using the http_proxy and https_proxy environment variables, which we set for you), and has a generally much better API.

However, even if you used requests, it wouldn't work, because you really are trying to access non-whitelisted sites from your web app. When you hit the URL http://sahildua2305.pythonanywhere.com/expand with parameters {'url': 'http://tuq.in/sahil'}, your function expandURL is called with the url parameter set to "http://tuq.in/sahil", which then calls unshorten_me with the url parameter set to "http://tuq.in/sahil", which in turn tries to use httplib to access the URL http://tuq.in/sahil. As tuq.in is not on our whitelist, even if you were using a proxy-enabled HTTP library like requests, it would be blocked.

I should add -- we could potentially whitelist tuq.in. But there could easily be other shorteners that you'd like to use which we couldn't whitelist.

You're making a request in your web app to http://tuq.in/sahil and that's what is being blocked.