Twisted.internet.error.CannotListenError,Address already in use - python

I tried to run scrapy spiders in a flask app, and there is a API in github Arachne.But there is something wrong when I run the demo project in my mac.The app.py looks like this:
app = Arachne(__name__)
resource = WSGIResource(reactor, reactor.getThreadPool(), app)
site = Site(resource,
logFormatter=http.combinedLogFormatter,
logPath="logs/"+datetime.now().strftime("%Y-%m-%d.web.log"))
reactor.listenTCP(8080, site)
if __name__ == '__main__':
reactor.run()
But when I run this file,there is an error:
twisted.internet.error.CannotListenError: Couldn't listen on any:8080: [Errno 48] Address already in use.
I tried to solve this by the method which is mentioned in this question:twisted python server port already in use.And the result after I use the command to kill the process in my terminal like this:
sunzhendeMacBook-Pro:~ Rabbit$ lsof -n -iTCP:8080 -sTCP:LISTEN
COMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAME
Python 5151 Rabbit 3u IPv4 0x738fcf82e37369b9 0t0 TCP *:http-alt (LISTEN)
However,when I run the demo project the Address already in use problem still there.I've also tried to change another port number, but the program has no result if I change the port.
So I wonder who has ever used Arachne API has encountered this problem and can give me a solution.Or does anybody has other good way to run multi spiders in flask app?

Related

How to serve CherryPy application in mulitple ports independently?

I am using CherryPy to serve my application in multiple ports say 8080 and 8081
cherrypy.server.unsubscribe()
for port in [8080, 8081]:
server = Server()
server.socket_port = port
server.socket_host = "0.0.0.0"
server.thread_pool = 100
server.subscribe()
cherrypy.engine.start()
cherrypy.engine.block()
With this the application is being served as expected on both the ports. Now due to some reason I want to stop the server of a specific port and other being served normally. When I stop the process on a particular port with the following command,
fuser -k "$port"/tcp
All the process on the ports in which the application was started (8080, 8081) are also being killed. Is this an expected behaviour ?
If yes, is there anyway I can achieve serving the application independently without affecting the other ports on which it is running ? (Other than like I should change the port in the source code and run it again manually)
If no, what is the mistake I am doing here ?
Any help would be appreciated!

Finding the actual call from flask to run on port 5000

This question might be a little wierd, but guy whome I do not have contact with wrote a program, which I should adapt.
it started a local python program, which runs with flask on port 5000 so when i write :5000 I can access a webpage with a few buttons but the .py file I found doesn`t set a port anywhere within the program it only calls:
app.run(debug=False, host='0.0.0.0')
and a couple of
#app.route('/DoSomething', methods=['POST', 'GET']
in the folder are a few more files, which doesnt contain a port either ... when I type
cat ./* | grep :5000
I find a few lines, but I have no plan where they are coming for
I am not really an expert on this topic - never worked with flask or created any applications that can be accessed with an URL ... Does someone probably know what I am missing here / where I probably find more?
As the line you reference does not include a value for the port keyword argument, it is defaulted to port 5000 which is the expected behavior per the docs.
In terms of finding the actual line where this happens, that line is in the run method of the Flask application object in the flask source code:
_host = '127.0.0.1'
_port = 5000
server_name = self.config.get('SERVER_NAME')
sn_host, sn_port = None, None
if server_name:
sn_host, _, sn_port = server_name.partition(':')
host = host or sn_host or _host
port = int(port or sn_port or _port)
This code defaults host and port and then overrides them based on the SERVER_NAME defined in the application config or the passed host and port information.
A note on your grep one-liner
This is off-topic to the initial question, but:
cat ./* | grep :5000
Should be re-written as:
grep 5000 ./*
Which will annotate the matching lines with the filename, and save you a useless use of cat.

Accessing a socket coded using python TCPServer from outside (external machine)

I am making python server using TCPServer. Things that I can do are:
1. use curl from other terminal (curl 10.157.41.14:8444 --data "var1=10&var2=15")
2. use firefox in Xming and type "localhost:8444"
The problem is that when I try to access the server from outside, I can not
I thought this is a problem with the code but I could not find any error with my code.
This is how I configure host and port on my python code:
from SocketServer import TCPServer, StreamRequestHandler
import socket
class MyRequestHandler(StreamRequestHandler):
def handle(self):
print "A client tried to connect";
self.wfile.write("success/n this is a replay from the server");
server = TCPServer((socket.gethostname(), 8444), MyRequestHandler)
host, port = server.socket.getsockname()
address = host + ":" + str(port)
message = "Started string-length server at " + address
print message
server.serve_forever()
I tried changing
server = TCPServer((socket.gethostname(), 8444), MyRequestHandler)
to
server = TCPServer('', 8444), MyRequestHandler);
and to:
server = TCPServer('0.0.0.0', 8444), MyRequestHandler);
None of these works on my case. So what I did next is trying to find if it is a problem in my network configuration or firewall. The problem is that I am not an export on these. Here is what I did:
user#ip-10-157-41-14:/var/www/server$ netstat -tnlpen | grep "8444\|PID"
(Not all processes could be identified, non-owned process info will not be shown, you would have to be root to see it all.)
Proto Recv-Q Send-Q Local Address Foreign Address State User Inode PID/Program name
tcp 0 0 10.157.41.14:8444 0.0.0.0:* LISTEN 1014 106226915 31541/python
Then, I did this to find out more about the firewall:
user#ip-10-157-41-14:/var/www/server$ sudo iptables -L
[sudo] password for user:
Chain INPUT (policy ACCEPT)
target prot opt source destination
Chain FORWARD (policy ACCEPT)
target prot opt source destination
Chain OUTPUT (policy ACCEPT)
target prot opt source destination
another thing I did was opening two terminals (in the same machine)
on terminal-1 I did "nc -l 5000"
on terminal-2 I did "nc 10.157.41.14 5000"
It seems to work. but I do not have access to another Linux machine to try it from another machine.
The problem is that I do not understand the above 2 commands. I spent hours trying to search stackoverflow and other sites for a solution but I did not find a solution that works for me.
In the past(in the same machine), I was able to write cgi python server where I call it using ajax call but I had to write a .htaccess file in the same directory of the python that I was using. The following is my .htaccess file:
Options +ExecCGI
AddHandler cgi-script .py
But the problem I am having now is completely different problem.
My problem turned out to be an Amazon EC2 specific problem.
I am running my server in an instance in Amazon EC2
Amazon instance is located in a Virtual Private Cloud (VPC) with an IP.
You decide if the instance is exposed to the Internet or to remain private.
So, there is an extra level of protection on top of the the EC2 instance.
from the EC2 Dashboard, you can specify open port numbers and close other ones.
It does not matter what I do in the instance level because the configuration in the dashboard is not allowing ports to be open. So, basically I added open ports to the security group in Amazon EC2 and it worked perfectly.

Problems with external visibility of Flask web-server

I have managed to to install flask and run the hello-world script:
from flask import Flask
app = Flask(__name__)
#app.route('/')
def hello_world():
return 'Hello World!'
if __name__ == '__main__':
app.run()
I was impressed how easy it was. Then I wanted to make my web-server visible externally. As recommended, I put host='0.0.0.0' as the argument of run function. Then I found my IP address (in Google) and put it in the address line of my web browser (while the hello-world-script was running).
As a result I got: "A username and password are being requested" and a dialogue box where I need to put a user name and password. I am not sure but I think it comes from my wireless network. Is there a way to change this behaviour?
How are you trying to run your application? If you run flask as app.run() - flask creates its own WSGI server on your host (by default 127.0.0.1) and port (by default 5000) (need permissions if port < 1000). If you run flask using nginx + WSGI or etc. your server resolves host and port.
Now it looks like you want get application by port which resolved your server like nginx or Apache. Try to get flask application by http://your-server-host-or-ip:5000 with the default port or try to change the port (set explicit) like app.run('0.0.0.0', 8080) and get it by http://your-server-host-or-ip:8080.
By the way, you can always get IP address using command-line tools e.g. ifconfig for Unix-like systems, or ipconfig /all for Windows.
To elaborate a little bit onto what #tbicr said, that password prompt indicates that you're trying to connect to your IP on port 80, which is most likely hosting an administration page for your router/modem. You want to connect to your IP on port 5000, the default port for Flask apps run with app.run().

How to declare ports in Cloud9 using Python

I'm new to using Cloud9 IDE (c9) and so far it looks great, except a few minor things.
I see from the docs that to start up a simple node.js http server, you have to pass in process.env.PORT in place of the regular port such as "8080".
Node Hello World example:
var http = require('http');
http.createServer(function (req, res) {
res.writeHead(200, {'Content-Type': 'text/plain'});
res.end('Hello World\n');
}).listen(process.env.PORT, process.env.IP);
What I want to know is, on c9, can you only start services on ports using javascript / node.js? Or do other languages work just as well, perhaps with some other method of passing the port? Specifically python + Twisted?
I uploaded some twisted code that was working locally for me, but wouldn't work on c9 because it was trying to access local ports (which are already in use). Here is the error
twisted.internet.error.CannotListenError: Couldn't listen on any:8080: [Errno 98] Address already in use.
How would one make the following example work, if even possible, running on c9?
Python+Twisted Hello World example
from twisted.web import server, resource
from twisted.internet import reactor
class Simple(resource.Resource):
isLeaf = True
def render_GET(self, request):
return "<html>Hello, world!</html>"
site = server.Site(Simple())
reactor.listenTCP(8080, site)
reactor.run()
Initial searches through the documentation and github issues did not turn much up. I'm hoping this is possible and I just missed the right parameter to pass.
Edit: Updated output below
Node Code
console.log(process.env.PORT)
console.log(process.env.IP)
Terminal output
Running Node Process
Tip: you can access long running processes, like a server, at 'http://private-cloud.mrchampe.c9.io'.
Important: in your scripts, use 'process.env.PORT' as port and 'process.env.IP' as host.
8080
127.6.70.129
Python Code
import os
print os.environ["PORT"]
print os.environ["IP"]
Terminal output
Running Python Process
8080
127.6.70.129
Twisted code
import os
import twisted
from twisted.web import server, resource
from twisted.internet import reactor
class Simple(resource.Resource):
isLeaf = True
def render_GET(self, request):
return "<html>Hello, world!</html>"
site = server.Site(Simple())
reactor.listenTCP(int(os.environ["PORT"]), interface=os.environ["IP"])
reactor.run()
Terminal Output
Running Python Process
hello world
Traceback (most recent call last):
File "python/hello.py", line 17, in <module>
reactor.listenTCP(int(os.environ["PORT"]), interface=os.environ["IP"])
TypeError: listenTCP() takes at least 3 non-keyword arguments (2 given)
The listenTCP TypeError is strange because 2 arguments works locally but not on Cloud9. I don't see why using these arguments does not work.
I have the above code hosted on this public Cloud9 project for anyone to take a look. Thanks!
process.env.PORT and process.env.IP from Node.js sound like os.environ["PORT"] and os.environ["IP"] in Python. Perhaps you can try:
reactor.listenTCP(int(os.environ["PORT"]), site, interface=os.environ["IP"])
Probably this is limitation of c9 environment management, so users dont abuse their service too much. I would assume that they have some level of management for Node.js used resources and thus allow these to open ports.
If this was the case and I had to work with cloud9, I would probably approach this as follows:
- create Node.js service which would act as a proxy, listening on twisted behalf
- create new reactor with overriden listenTCP and listenUDP methods, which would bind these to Node.js proxy service.
The way how proxy would work is as follows, Node.js would initially listen on one "management" TCP port. Then, when twisted service starts up, it would create a TCP connection between Node.js and itself through that port. Then, whenever listenTCP or listenUDP is called, these commands would then be dispatched to Node.js service, which in return would open the port and all of the comunication through that port would then be proxied to twisted through that existing TCP connection.
It's worth mentioning that Jean-Paul's answer worked for me as well, but I had to use 'address' instead of 'interface':
http_server.listen(int(os.environ.get("PORT")), address=os.environ["IP"])

Categories

Resources