ghp
Posts: 1517
Joined: Wed Jun 12, 2013 12:41 pm
Location: Stuttgart Germany
Contact: Website

subprocess question

Sat Feb 09, 2019 9:45 pm

Hello,
I write some code where a python3 script is loading other scripts from an usb-stick. These scripts can be shell- or python scripts.
Found that running python scripts results in a problem related to using subprocess.run with arguments in arrayor string .

The problem is, that when using arguments as array then python opens in interactive mode. Unexpected. Have no clue where the problem is. Appreciate help.

The code can be reduced to these fragments:

The code "a.py" is basic.

Code: Select all

print("hallo A")
The code "b.py" shows three options, the first two result in an interactive process to open. Comment the other "a =" to enable an option.

Code: Select all

import subprocess
# Option A
# causes an python process to open with interactive mode
#
a = [ "python3", "a.py"]

# Option B
# same problem
#
a = [ "/usr/bin/python3", "a.py"]

# Option C
# works as expected when no array but string is used.
#
a = "python3 a.py"

# execute the command
subprocess.run( a , shell=True)

print("hallo B")
Here the output for the Options A, B

Code: Select all

pi@raspberrypi:~ $ python3 b.py
Python 3.5.3 (default, Sep 27 2018, 17:25:39)
[GCC 6.3.0 20170516] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> quit()      <-- manually entered
hallo B
pi@raspberrypi:~ $
Option C results in

Code: Select all

pi@raspberrypi:~ $ python3 b.py
hallo A
hallo B
pi@raspberrypi:~ $

Andyroo

Re: subprocess question

Sat Feb 09, 2019 10:24 pm

Reading https://docs.python.org/3.5/library/sub ... -arguments it states the args for this function is based on Popen

Looking at https://docs.python.org/3.5/library/sub ... cess.Popen it seems that
By default, the program to execute is the first item in args if args is a sequence.
Assuming the array is not a string the program is the first part i.e. the Python interpreter in interactive mode so ignoring the program name.

User avatar
paddyg
Posts: 2555
Joined: Sat Jan 28, 2012 11:57 am
Location: UK

Re: subprocess question

Sat Feb 09, 2019 10:26 pm

Hi, critically you don't show the run() statements for A and B options. You might get the behavior you describe if you kept 'shell=True', which you probably don't want for passing a list of strings. i.e.

Code: Select all

subprocess.run(a)
should work
also https://groups.google.com/forum/?hl=en-GB&fromgroups=#!forum/pi3d

User avatar
Paeryn
Posts: 2986
Joined: Wed Nov 23, 2011 1:10 am
Location: Sheffield, England

Re: subprocess question

Sun Feb 10, 2019 12:20 am

ghp wrote:
Sat Feb 09, 2019 9:45 pm
Hello,
I write some code where a python3 script is loading other scripts from an usb-stick. These scripts can be shell- or python scripts.
Found that running python scripts results in a problem related to using subprocess.run with arguments in arrayor string .

The problem is, that when using arguments as array then python opens in interactive mode. Unexpected. Have no clue where the problem is. Appreciate help.

The code can be reduced to these fragments:

The code "a.py" is basic.

Code: Select all

print("hallo A")
The code "b.py" shows three options, the first two result in an interactive process to open. Comment the other "a =" to enable an option.

Code: Select all

import subprocess
# Option A
# causes an python process to open with interactive mode
#
a = [ "python3", "a.py"]

# Option B
# same problem
#
a = [ "/usr/bin/python3", "a.py"]

# Option C
# works as expected when no array but string is used.
#
a = "python3 a.py"

# execute the command
subprocess.run( a , shell=True)

print("hallo B")
Here the output for the Options A, B

Code: Select all

pi@raspberrypi:~ $ python3 b.py
Python 3.5.3 (default, Sep 27 2018, 17:25:39)
[GCC 6.3.0 20170516] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> quit()      <-- manually entered
hallo B
pi@raspberrypi:~ $
Option C results in

Code: Select all

pi@raspberrypi:~ $ python3 b.py
hallo A
hallo B
pi@raspberrypi:~ $
That behaviour is because you used shell=True, in this case if the command is a list then the arguments are assigned to the shell executing the command, not the command which that shell goes on to execute. Also in this case the first argument after the command is the name given to the shell (its $0).

Code: Select all

import subprocess

a = [ "echo $0 $1; /usr/bin/python3 $1", "sub_shell_name", "a.py" ]

subprocess.run(a, shell=True)

print("Hello b")
As you can (hopefully) see, the first string is the command that the shell will run, the second string is $0 of that shell, the third string is $1. Oh, I have a.py printing its sys.argv as well

Code: Select all

pi@rpi3:~/Programming/pyth/sb $ python3 b.py
sub_shell_name a.py
Hello a:  ['a.py']
Hello b
She who travels light — forgot something.

Return to “Python”