10

I have a situation where I need one python script to be running in a continuous loop, and I need to pass parameters into it from another script which will run when an action occurs.

The second script will be triggered by a website using cgi, I have this working fine. The continuous loop should take in parameters read out by the cgi script (and then send info via a serial port).

For the specific problem I can't have the cgi script sending the data via serial directly as each time it runs it resets the serial port.

I can't seem to find any information on this kind of setup. Are there any methods or libraries I could look into for this or better ways of approaching it?

dsolimano
  • 8,870
  • 3
  • 48
  • 63
Ger
  • 754
  • 1
  • 9
  • 33
  • Have you thought about making the 2nd script running flask or something and accept the parameters as http get parameters? – JoelWilson Sep 04 '13 at 14:27

2 Answers2

11

I would use a socket connection. Essentially you are writing a very simple server that only takes one connection at a time

import socket
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.bind(("localhost", 9988))
s.listen(1)

while True:
    conn, addr = s.accept()
    data = conn.recv(1024)
    conn.close()
    my_function_that_handles_data(data)

s.accept() is a blocking call. It waits for a connection. Then you do a read on the connection. In this case we are assuming the length of the parameters are only 1024 bytes. Then we do something with the data we received from the socket and wait for another connection.

The client could look like this:

import socket
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect(("localhost", 9988))
s.sendall('My parameters that I want to share with the server')
s.close()

The nice thing about this is that in the future if the client and server are no longer running on the same machine then it's a simple matter of changing "localhost" to the actual ip address or domain name you are going to hit.

aychedee
  • 24,871
  • 8
  • 79
  • 83
  • 2
    This looks like it might be perfect, I've stumbled across sockets before but wasn't sure how they'd work for this or how to use them, thanks for the simple example. Will try it out later on. – Ger Sep 04 '13 at 15:29
  • 1
    Sockets are pretty flexible. There are lots of different types of sockets you can create. They don't have to be across the network. If you are using Linux you can create a domain socket that is just routed via the kernel. – aychedee Sep 04 '13 at 18:16
  • 2
    The next step is to create a server that stores away the connections and uses epoll to be notified every time there is some data to be read from them. Before you know it you've written an async socket server. – aychedee Sep 04 '13 at 23:09
  • That sounds interesting, but I'm not really sure I understand... would you suggest I look into this? The way I'm intending to use this is to have a website (mobile) that has some controls on it (on, off, speed slider), and this website will be used to control a DIY quadcopter (raspberry pi and arduino). Your code has the website passing commands correctly now, could you see any use for an async socket server here? – Ger Sep 05 '13 at 08:30
  • 2
    Asyncronicity (epoll) is useful when you have a high demand on resources (ie: many concurrent users). While one user is waiting for a particular resource, the server-process can serve the next user, or process other resources. If your website is intended for a single user to control the quadcopter, then blocking (waiting for resources) shouldn't be a problem. – Jo Are By Sep 05 '13 at 08:47
  • Nope, no need to make it async. But I was just explaining how one would take the next step to do so. If for example you had multiple quadcopters and users trying to control them at the same time. Instead of running a new process for each quadcopter you could use one process that processed the requests async. – aychedee Sep 05 '13 at 13:02
  • In Python 3.5.2 one needs to send a bytes-like object instead of a string. e.g. `b'My parameters'` instead of `'My parameters'`. – Matt Kleinsmith Dec 02 '17 at 12:04
  • can we add a function on server side that client can access by connecting to server on given port ? – Ciasto piekarz Jan 19 '21 at 17:02
  • That's what is described in the answer. `my_function_that_handles_data` would be the function. – aychedee Jan 19 '21 at 18:27
  • sorry you misunderstood my point, I want to be able to call the function on the server side from client end via socket connection object ! kind of persistent connection – Ciasto piekarz Jan 19 '21 at 18:46
  • A socket, as described in the answer above, is a persistent, bi-directional method for communication. You don't have to call conn.close. You can use the conn.send, and conn.recv method as many times as you want. If you want to route certain messages, based on their content, to particular functions then you can. – aychedee May 12 '21 at 08:45
2

The general concept of what you're describing is called Inter-Process Communication (Python IPC).

In python this can be done by sockets and signals.

There are also higher level interfaces built on top of/using sockets; asyncore and asynchat.

Jo Are By
  • 3,293
  • 1
  • 11
  • 11