Error when running tornado Webserver in terminal - python

I am trying to run a tornado webserver in the terminal, but when I run it I simply get a space which is completely empty, and then I have no way of closing the server. Right now I am trying the hello world example.
import tornado.ioloop
import tornado.web
class MainHandler(tornado.web.RequestHandler):
def get(self):
self.write("Hello, world")
application = tornado.web.Application([
(r"/", MainHandler),
])
if __name__ == "__main__":
application.listen(8888)
tornado.ioloop.IOLoop.instance().start()
Any help would be much appreciated. I have already taken a look at the getting Tornado working question, and the answers there did not solve the issue.

All you need to do is type this URL in your browser
http://127.0.0.1:8888
But if you do see any error messages
Try changing your port.May be it is being used by other program
application.listen(7777)
Now point your browser to
http://127.0.0.1:7777
Stopping the server
A simple ctrl+c would kill the process.But if you want to do more cleaner way
try:
tornado.ioloop.IOLoop.instance().start()
except KeyboardInterrupt:
tornado.ioloop.IOLoop.instance().stop()

Related

Program gets stuck with tornado

I'm trying to make a Raspberry Pi send plain text to my phone over my local network, from where I plan to pick it up.
I tried the following "hello world"-like program from their official website, but I cannot get it to proceed after a point.
import tornado.ioloop
import tornado.web
class MainHandler(tornado.web.RequestHandler):
def get(self):
self.write("Ugh, the world? Well.. hello, I guess")
application = tornado.web.Application([
(r"/", MainHandler),
])
application.listen(8881)
tornado.ioloop.IOLoop.instance().start()
# I cannot get this line to execute!!
print("Hi!!")
Experience: basics of Python, intermediate with Arduino C++, none in networking/web
You're trying to print to STDOUT after starting the event loop, so that print statement never sees the light of the day. Basically, you're creating a HTTP server at port 8881 that is constantly listening for requests. Whatever logic you wish the server to do needs to be in a callback, like MainHandler
import tornado.ioloop
import tornado.web
class MainHandler(tornado.web.RequestHandler):
def get(self):
self.write("Ugh, the world? Well.. hello, I guess")
# All your SMS logic potentially goes here
self.write("Sent SMS to xyz...")
application = tornado.web.Application(
[
(r"/", MainHandler),
]
)
application.listen(8881)
tornado.ioloop.IOLoop.instance().start()
Then trigger the endpoint by making an HTTP call
curl <IP ADDRESS OF YOUR PI>:8881
This is because Tornado's IOLoop.start() method is a "blocking" call, which means that it doesn't return until some condition is met. This is why your code "gets stuck" on that line. The documentation for this method states:
Starts the I/O loop.
The loop will run until one of the callbacks calls stop(), which will
make the loop stop after the current event iteration completes.
Typically, a call to IOLoop.start() will be the last thing in your program. The exception would be if you want to stop your Tornado application and then proceed to do something else.
Here are two possible solutions to your problem, depending on what you want to accomplish:
call self.stop() from the handler. This will stop the Tornado application, IOLoop.start() will return, and then your print will execute.
call print("Hi!!") from your handler.

Close port using Tornado web server

I am running a Tornado web server to send GET and POST requests. I want to be able to shut it down to do modifications on it and start it when finished to test it. But I cant, the port used is in used forever...
def startTornado():
application = tornado.web.Application([
(r"/", MainHandler),
])
application.listen(80)
tornado.ioloop.IOLoop.instance().start()
print "Server is running"
def stopTornado():
ioloop = tornado.ioloop.IOLoop.instance()
ioloop.add_callback(ioloop.stop)
print "Asked Tornado to exit"
if __name__ == "__main__":
#stopTornado()
startTornado()
I checked all the answer on the web, but I it doesnt help me.
ioloop = tornado.ioloop.IOLoop.instance()
ioloop.add_callback(ioloop.stop)
Doesnt close the port. It is still in use :
TCP 0.0.0.0:80 PC-1:0 LISTENING
[python.exe]
Does anyone have an idea ?
To close the port, you must call HTTPServer.close(), not IOLoop.stop() (a stopped IOLoop can be restarted). This means using
server = HTTPServer(application)
server.listen(80)
instead of the Application.listen convenience method.

How to write a Tornado listener correctly?

I wanted to write a server background listener to listen to dozens of clients sending commands to this background listener on TCP port 8888. Command format is "http://myip/?c="ClientCommand=A5"
Those clients could be sending commands at the same time or different time. Also, these clients will stay connected and sending few different commands until disconnect by client themselves. All the commands received by the background listener will be written to a MySQL DB.
After few days of study, I found Python + Tornado framework could be a good tool to do this. However, I have tried few days with examples from the web and I still don't know how to program this background listener.
Here is an example I found on a blog and it worked...How do I modify the code below to do the background listener? I know I need to use GET to get parameters from the URL. I have tried get(self.get), but I got error of invalid syntax...
Thanks for your help.
import tornado.ioloop
import tornado.web
class IndexHandler(tornado.web.RequestHandler):
def get(self):
self.write("Hello, Tornado!")
if __name__ == "__main__":
application = tornado.web.Application([
(r"/", IndexHandler)
])
application.listen(8888)
tornado.ioloop.IOLoop.current().start()

Handling stdin with tornado

How to listen for events that happen on stdin in Tornado loop?
In particular, in a tornado-system, I want to read from stdin, react on it, and terminate if stdin closes. At the same time, the Tornado web service is running on the same process.
While looking for this, the most similar I could find was handling streams of an externally spawned process. However, this is not what I want: I want to handle i/o stream of the current process, i.e. the one that has the web server.
Structurally, my server is pretty much hello-world tornado, so we can base the example off that. I just need to add an stdin handler.
You can use the add_handler method on the IOLoop instance to watch for events on stdin.
Here's a minimal working example:
from tornado.ioloop import IOLoop
from tornado.web import Application, RequestHandler
import sys
class MainHandler(RequestHandler):
def get(self):
self.finish("foo")
application = Application([
(r"/", MainHandler),
])
def on_stdin(fd, events):
content = fd.readline()
print "received: %s" % content
if __name__ == "__main__":
application.listen(8888)
IOLoop.instance().add_handler(sys.stdin, on_stdin, IOLoop.READ)
IOLoop.instance().start()

Stopping a tornado application

Let's take the hello world application in the Tornado home page:
import tornado.ioloop
import tornado.web
class MainHandler(tornado.web.RequestHandler):
def get(self):
self.write("Hello, world")
application = tornado.web.Application([
(r"/", MainHandler),
])
if __name__ == "__main__":
application.listen(8888)
tornado.ioloop.IOLoop.instance().start()
Is there a way, after the IOloop has been started and without stopping it, to essentially stop the application and start another one (on the same port or on another)?
I saw that I can add new application (listening on different ports) at runtime, but I do not know how I could stop existing ones.
Application.listen() method actually creates a HTTPServer and calls its listen() medthod. HTTPServer objects has stop() method which is probably what you need. But in order to do it you have to explicitly create HTTPServer object in your script.
server = HTTPServer(application)
server.listen(8888)
tornado.ioloop.IOLoop.instance().start()
#somewhere in your code
server.stop()
Here is a gist about how to gracefully and safely shutdown the tornado ioloop.
https://gist.github.com/nicky-zs/6304878
However, you can refer to this implementation to achieve your goal.
To add to #Alex Shkop's answer a few years later, as of Tornado 4.3 .listen() returns a reference to its HTTPServer!
https://www.tornadoweb.org/en/stable/web.html#tornado.web.Application.listen
server = app.listen()
... # later
server.stop()
Further, if you're working in a Jupyter notebook and for some reason need a Tornado server, you can try to close the HTTPServer before you recreate it to avoid OSError: [Errno 98] Address already in use on re-running the cell
# some Jupyter cell
#
import tornado.web
try:
server.stop() # NameError on first cell run
except Exception as ex:
print(f"server not started to stop: {repr(ex)}")
else: # did not raise NameError: server was running
print(f"successfully stopped server: {server}")
app = tornado.web.Application(...)
server = app.listen(9006) # arbitrary listening port

Categories

Resources