If you want your script to return values, just do return [1,2,3] from a function wrapping your code but then you'd have to import your script from another script to even have any use for that information:

Return values (from a wrapping-function)

(again, this would have to be run by a separate Python script and be imported in order to even do any good):

import ...
def main():
    # calculate stuff
    return [1,2,3]

Exit codes as indicators

(This is generally just good for when you want to indicate to a governor what went wrong or simply the number of bugs/rows counted or w/e. Normally 0 is a good exit and >=1 is a bad exit but you could inter-prate them in any way you want to get data out of it)

import sys
# calculate and stuff
sys.exit(100)

And exit with a specific exit code depending on what you want that to tell your governor. I used exit codes when running script by a scheduling and monitoring environment to indicate what has happened.

(os._exit(100) also works, and is a bit more forceful)

Stdout as your relay

If not you'd have to use stdout to communicate with the outside world (like you've described). But that's generally a bad idea unless it's a parser executing your script and can catch whatever it is you're reporting to.

import sys
# calculate stuff
sys.stdout.write('Bugs: 5|Other: 10\n')
sys.stdout.flush()
sys.exit(0)

Are you running your script in a controlled scheduling environment then exit codes are the best way to go.

Files as conveyors

There's also the option to simply write information to a file, and store the result there.

# calculate
with open('finish.txt', 'wb') as fh:
    fh.write(str(5)+'\n')

And pick up the value/result from there. You could even do it in a CSV format for others to read simplistically.

Sockets as conveyors

If none of the above work, you can also use network sockets locally *(unix sockets is a great way on nix systems). These are a bit more intricate and deserve their own post/answer. But editing to add it here as it's a good option to communicate between processes. Especially if they should run multiple tasks and return values.

Answer from Torxed on Stack Overflow
Top answer
1 of 1
146

If you want your script to return values, just do return [1,2,3] from a function wrapping your code but then you'd have to import your script from another script to even have any use for that information:

Return values (from a wrapping-function)

(again, this would have to be run by a separate Python script and be imported in order to even do any good):

import ...
def main():
    # calculate stuff
    return [1,2,3]

Exit codes as indicators

(This is generally just good for when you want to indicate to a governor what went wrong or simply the number of bugs/rows counted or w/e. Normally 0 is a good exit and >=1 is a bad exit but you could inter-prate them in any way you want to get data out of it)

import sys
# calculate and stuff
sys.exit(100)

And exit with a specific exit code depending on what you want that to tell your governor. I used exit codes when running script by a scheduling and monitoring environment to indicate what has happened.

(os._exit(100) also works, and is a bit more forceful)

Stdout as your relay

If not you'd have to use stdout to communicate with the outside world (like you've described). But that's generally a bad idea unless it's a parser executing your script and can catch whatever it is you're reporting to.

import sys
# calculate stuff
sys.stdout.write('Bugs: 5|Other: 10\n')
sys.stdout.flush()
sys.exit(0)

Are you running your script in a controlled scheduling environment then exit codes are the best way to go.

Files as conveyors

There's also the option to simply write information to a file, and store the result there.

# calculate
with open('finish.txt', 'wb') as fh:
    fh.write(str(5)+'\n')

And pick up the value/result from there. You could even do it in a CSV format for others to read simplistically.

Sockets as conveyors

If none of the above work, you can also use network sockets locally *(unix sockets is a great way on nix systems). These are a bit more intricate and deserve their own post/answer. But editing to add it here as it's a good option to communicate between processes. Especially if they should run multiple tasks and return values.

🌐
Real Python
realpython.com › python-return-statement
The Python return Statement: Usage and Best Practices – Real Python
June 14, 2024 - But if you’re writing a script and you want to see a function’s return value, then you need to explicitly use print(). ... You can use a return statement to return multiple values from a function.
Top answer
1 of 2
6

Within sh which is actually dash on Ubuntu the builtin command return can returns only numerical values - exit statuses, which have a meaning in a context of a function or sourced script. Source man sh:

The syntax of the return command is

return [exitstatus]

Everything other with your shell script looks correct. I think you need to use echo $COLOR instead return and suppress other echo-es.

In case you need to return more data to the main script you can output everything as one line and divide the separate fields by some character that will play role of a delimiter in the main script on which base you can convert the string into an array. For example (where , is our delimiter and -n will suppers the newline character within echo):

echo -n "$COLOR","$exitstatus"

The other information that is provided by the script and is not required by the main script could be redirected to some log file:

$ cat whiptail.sh
#!/bin/sh
log_file='/tmp/my.log'

COLOR=$(whiptail --inputbox "What is your favorite Color?" 8 78 Blue --title "Example Dialog" 3>&1 1>&2 2>&3)
exitstatus=exitstatus = 0 ]; then
    echo "User selected Ok and entered $COLOR" > "$log_file"
    echo -n "$COLOR","$exitstatus"
else
    echo "User selected Cancel."  >> "$log_file"
    echo -n "CANCEL","$exitstatus"
fi

Unfortunately I don't have much experience with Python, but here is a sample .py script that can handle the output of the above .sh script (reference):

$ cat main-script.py
#!/usr/bin/python
import subprocess

p = subprocess.Popen(['./whiptail.sh'], stdout=subprocess.PIPE)
p = p.communicate()[0]
p = p.split(",")
print "Color:    " + p[0]
print "ExitCode: " + p[1]
2 of 2
0

I had a similar problem where I needed the return value from a shell command in my Python script.

The subprocess method check_output() helped me get the shell return code as a byte string in the Python file.

Here is the code:

return_value =subprocess.check_output("sudo raspi-config nonint get_spi", stderr=subprocess.STDOUT, shell = True)
print(return_value)


<<<b'1\n'
🌐
YouTube
youtube.com › how to fix your computer
PYTHON : Best way to return a value from a python script - YouTube
PYTHON : Best way to return a value from a python script [ Gift : Animated Search Engine : https://www.hows.tech/p/recommended.html ] PYTHON : Best way to r...
Published   December 5, 2021
Views   445
🌐
DigitalOcean
digitalocean.com › community › tutorials › python-return-statement
Python return statement | DigitalOcean
August 3, 2022 - The python return statement is used to return values from the function. We can use the return statement in a function only.
Find elsewhere
🌐
Cprogramming
cboard.cprogramming.com › c-programming › 130188-calling-python-script-obtaining-return-value.html
Calling a python script and obtaining a return value
One (extremely kludgy) way to do this would be to have C execute a system call to run the python script and then direct the output to a temporary file, and then after returning, have C open up that file and convert the string into a floating point value. But that approach seems to have a lot of rather undesirable characteristics.
🌐
McNeel Forum
discourse.mcneel.com › scripting
How to return a value from a script running inside another script? - Scripting - McNeel Forum
September 25, 2019 - I’d like to get the opinion of the Python gurus as to the correct way to handle this. I think I might be over-complicating it. Say I have Script A that returns a value. Could be a boolean, could be a numeric value, whatever. I want to run Script A inside Script B, but I want that value to be passed from Script A to Script B when Script B runs.
Top answer
1 of 2
1

Apache creates its own users to run its jobs. When run as a php command, you are almost surely running as some such Apache-created user that has different permissions than your user account. Accessing the GPIO requires special permission, which the php user probably doesn't have. That will cause it to fail when called, which is exactly what you are seeing.

To further debug this, you should check the error logs created when the job fails and possibly identify the user that is executing that job. These links will help:

  • https://stackoverflow.com/questions/7771586/how-to-check-what-user-php-is-running-as
  • https://stackoverflow.com/questions/5127838/where-does-php-store-the-error-log-php5-apache-fastcgi-cpanel

Summarizing the key point about the error logging, the error usually appears under /var/log/apache2 on the Pi. (You'll see other potential locations listed for other hardware and software options at the stack overflow questions since they are more general.)

To address the underlying permissions error, if that's what it ultimately is, you may have a couple of options. You might be able to grant the appropriate permissions to the php user, or your might run it with sudo from your php script. That, in turn, may require you to add the php use to the list of sudoers. Be careful with either option - especially if there's public access - because you'll be allowing external control of the pins on your Pi!

Having mentioned how to do this, I think it's worth noting that this probably indicative of a bad design anyway. Based on what you said, it seems like php is the wrong tool for this job. If you must allow changes in state to your Pi via web, you're probably better using cgi-bin programs instead. Usually php is for serving dynamic content in the webpage, not for changing the state of the server. (In this case, the Pi is the server.) That's a whole different set of questions and issues though.

2 of 2
1

It's almost certainly a permissions issue. Ordinarily, you'd just add www-data to the gpio group (usermod -aG gpio www-data), but due to the fact you're accessing the SPI, it's a bit more complex than usual. You have two choices

  1. Run apache as root (not recommended)
  2. Run your script as a background process

Option 1 would quickly tell you if it's a permissions issue, and can be done by changing the user (you'll probably find it in /etc/apache2/envvars).

Option 2 is really a better approach, but is more work. What you need to think about is a long-lived process running in the background, and a way to interact with this from the web thread. This can be done by http/queue/file/fifo/socket among others. I'd recommend having a look at some of the react libraries, or ZeroMQ

With all that in mind, using the PHPi library, you can do this completely in PHP. Here's an example based off one of the examples in the library for interacting with that ADC.

include 'vendor/autoload.php';

use Calcinai\PHPi\Peripheral\SPI;
use Calcinai\PHPi\Pin\PinFunction;
use Calcinai\PHPi\External\ADC\Microchip\MCP3008;

$board = \Calcinai\PHPi\Factory::create();

//Flip the appropriate pins to their alt functions
$board->getPin(10)->setFunction(PinFunction::SPI0_MOSI);
$board->getPin(9)->setFunction(PinFunction::SPI0_MISO);
$board->getPin(11)->setFunction(PinFunction::SPI0_SCLK);
$board->getPin(8)->setFunction(PinFunction::SPI0_CE0_N);

$adc = new MCP3008($board->getSPI(SPI::SPI0), 0);
$pin = $board->getPin(18);

//In 10-bit, will be between 0 and 1024
$value = $adc->getChannel(0)->read();
if($value > 500){
    $pin->high();
} else {
    $pin->low();
}

Usually you'd be running this as a process, rather than directly via apache.

🌐
EDUCBA
educba.com › home › software development › software development tutorials › python tutorial › python return value
Python Return Value | Learn the Examples of Python Return Value
January 8, 2024 - A python function can return a specified value anywhere within that function by using a return statement, which ends the function under execution and then returns a value to the caller.
Address   Unit no. 202, Jay Antariksh Bldg, Makwana Road, Marol, Andheri (East),, 400059, Mumbai
🌐
Flexiple
flexiple.com › python › return-in-python
How does return() in Python work? | Flexiple Tutorials | Python - Flexiple
The value of a - b is 50 The value of a * 10 is 100 · The return statement sends any object from the function back to the caller code.
🌐
Python
python-list.python.narkive.com › Guc5JaIR › return-a-value-to-shell-script
return a value to shell script
I am executing a python script in a shell script. The python script actually returns a value. So, can I get the return value in a shell script? If yes, then help me out. There are two ways to "return" something to a shell script. 1) To return a success/fail indication, use sys.exit(n).
🌐
Stack Exchange
blender.stackexchange.com › questions › 269616 › how-to-get-return-values-when-i-run-blender-script-from-command-line
python - How to get return values when I run blender script from command line? - Blender Stack Exchange
import bpy import argparse import sys def calculation(input_value): print(some_value) return some_value parser = sys.argv calculation(str(parser[-1])) I want to get value of some_value when I launch script.py as cli command in launcher.py: blender ./data.blend --background --python script.py -- input_value · I can do that with subprocess.check_output method in launcher.py. launcher.py: Launch script.py as subprocess and get some_value from print(some_value) line in script.py.
🌐
CSDN
devpress.csdn.net › python › 62fd0ddac677032930802a0d.html
store return value of a Python script in a bash script_python_Mangs-Python
This is not guaranteed to capture only the value passed to sys.exit, though. Anything else written to stderr will also be captured, which might include logging output or stack traces. ... Not sure why but in that case, I would write a main script and two other scripts... Mixing python and bash is pointless unless you really need to. import script1 import script2 if __name__ == '__main__': filename = script1.run(sys.args) script2.run(filename)
🌐
Particle
community.particle.io › the archive › raspberry pi
Trigger and return values from python script - Raspberry Pi - Particle
May 12, 2018 - I have a Raspberry pi running particle-agent and have been looking around for the best way to trigger an ultrasonic sensor. Is there a way that i cloud do that on the .ino file on the agent. I have gotten it to work with a python script, and thought of using the method “Process” where you ...