I need a python script that will run a script
January 24, 2017 8:00 AM   Subscribe

I have 2 Raspberry Pi's. I want to execute a python script on Pi_1 that will execute a python script on Pi_2. I want Pi_1 to send script parameters to Pi_2 and I want Pi_1 to retrieve the output of the Pi_2 script. I'm new to python and Linux. I'm learning a lot from Stack Exchange but I haven't been able to find anything related to the above. Anything that will get me on the right track would be appreciated.
posted by night_train to Computers & Internet (10 answers total) 3 users marked this as a favorite
 
Best answer: You could set up a flask server on Pi_2 with a REST endpoint. Pi_1 can post data to the Pi_2; Pi_2 can return a JSON object to be parsed by Pi_1.

Here's a guide on Flask on the Pi. Here's a guide on Flask-RESTful, a REST plugin for Flask.

I'm happy to answer any other questions.

Ignore the part of the first guide about serving webpages. What you're trying to do is create a webserver that takes basic input and serves basic output.

Here's an idiots guide to REST.

It shouldn't be hard but the concepts may be a little advanced.

Both machines will need to talk to each other over a network.
posted by teabag at 8:12 AM on January 24, 2017


Hmm probably shouldn't have said "idiot's guide"; more like "basic explanation".
posted by teabag at 8:17 AM on January 24, 2017


Best answer: What you're asking is remarkably tricky if you want to do it reliably with lots of data. But if you want something quick and dirty, have Pi_1 run the script on Pi_2 via ssh and capture the output. Here's one approach for the script on Pi_1. If you search for [Python ssh output] you'll find lots of other options, including extra libraries like paramiko.

teabag's suggestion of using HTTP and REST is a good approach to a more robust solution where you make Pi_2 a proper server.
posted by Nelson at 8:39 AM on January 24, 2017 [1 favorite]


One option without a shell session or setting up a server would be:

1. script1 on pi1 SCP a text file to pi2
2. pi2 can use inotifywait to trigger the python script2 to run and use that text file as an input
3. script2 would then scp the output file to pi1

See: manual for inotifywait
posted by czytm at 8:53 AM on January 24, 2017


If that wasn't clear, the script2 on pi2 would be triggered by detecting that the file has been updated (using inotifywait) with the new parameters to use.
posted by czytm at 8:58 AM on January 24, 2017


Best answer: Alternatively you could use TCP Sockets? https://pymotw.com/2/socket/tcp.html
posted by czytm at 9:01 AM on January 24, 2017


Best answer: But if you want something quick and dirty, have Pi_1 run the script on Pi_2 via ssh and capture the output.

This. I was about to suggest netcat but ssh is simpler.

For fancier stuff, it looks like RPyC (never used it myself) is relatively straightforward.
posted by neckro23 at 9:07 AM on January 24, 2017


Best answer: You can get quite amazingly complicated with all this stuff-- but lets assume that your Pi2 script is relatively short-running (e.g. it doesn't take 5 minutes to complete, only a few seconds).

From Pi1 you can do a simple `requests` command passing in your arguments, something like this:
import requests
arguments = {
    'who': 'abe',
    'what': 'cow',
    'when': 'now'
}
pi2_web_address = 'http://192.168.0.X:5000'
r = requests.post(url=pi2_web_address, json=arguments)
print(r.json())
That's going to send a POST request to our Pi2 webserver including the arguments we've defined, then wait for some json data back and print it, you'll need to specify the correct IP address. The Pi2 webserver code is pretty easy too:
from flask import Flask, request, jsonify

app = Flask(__name__)
app.secret_key = 'SHH!'

@app.route('/', methods=['post'])
def home():
    arguments = request.get_json()
    print(arguments)  # so we can access the arguments, eg:
    print(arguments["who"])

    # At this point we could run our logic, running the python
    # script you care about, either directly
    # by `import`-ing it and running it, or using
    # the subprocess library to run it externally, catching
    # it's output.

    results = 'whatever'
    return jsonify(results=results)

if __name__ == '__main__':
    app.run(debug=True, address='0.0.0.0')

You shouldn't use the built-in Flask webserver for production stuff, but it's okay if it's just a little thing you're tinkering with around your home/office. Look into using Gunicorn running behind nginx if you're looking for something more robust. The '0.0.0.0' tells Flask to bind the webserver to your physical network interface on your Pi, so you can access it across the network.
posted by Static Vagabond at 10:11 AM on January 24, 2017 [1 favorite]


Best answer: Flask and REST are way overkill for this. Here is a three-line script1.py that you can run on Pi_1 which executes script2.py on Pi_2 and displays the output.

import subprocess
output = subprocess.check_output(['ssh', 'username@Pi_2', 'script2.py'])
print output

Replace 'username@Pi_2' with your Linux account name and Pi_2's hostname or IP address. You'll also need

* passwordless SSH access for username@Pi_2 from Pi_1

* script2.py on Pi_2 must be made 'executable' (chmod +x script2.py)
posted by ldenneau at 10:43 AM on January 24, 2017 [4 favorites]


Best answer: Many thanks for the informative answers, the links and especially the example code. ldenneau's answer looks the more simple but I will learn a lot by trying them all. RPyC looks intriguing and the TCP sockets will help in another project I'm considering. The guide to REST was a huge help in my understanding of web services.
posted by night_train at 11:25 AM on January 24, 2017 [1 favorite]


« Older Litter Box Training the Elderly Cat   |   IUD and Oral? Newer »
This thread is closed to new comments.