2

I would like to run a shell script from Python 3 in Linux passing two arguments that contain file paths to two different files. The shell script then calls a programme written in Python 2.

In Python 3, I call the shell script like this:

import os
import sys    
os.chmod('/path/to/sh', 0o777)
subprocess.call(['/path/to/sh', '/path/to/file1', '/path/to/file2'], shell=True)

My shell script looks like this:

#!/bin/sh
set -x
path1=$1
path2=$2
python2 path/to/programme "$path1" "$path2"

Now, the file paths are empty, and the shell script returns something like python2 path/to/programme '' ''. Does someone know how I could correctly pass the file paths so that the programme written in Python 2 can read them?

Or is there even an easier solution such as using subprocess to directly call the programme written in Python 2?

  • 1
    Just drop `shell=True`. You are already providing a list of separate strings that are sufficient for the appropriate system-level `exec*` function `subprocess` will use. – chepner Jun 16 '20 at 16:28
  • Whatever you are hoping to accomplish, **`chmod 777` is *wrong* and *dangerous.*** You absolutely do not want to grant write access to executable or system files to all users under any circumstances. You will want to revert to sane permissions ASAP (for your use case, probably `chmod 755`) and learn about the Unix permissions model before you try to use it again. If this happened on a system with Internet access, check whether an intruder could have exploited this to escalate their privileges. – tripleee Jun 17 '22 at 07:48

2 Answers2

3

There is no need for the shell script. You can use subprocess to run python2 directly.

a.py

#!/usr/bin/env python3

import subprocess

subprocess.call(['python2', './b.py', 'foo', 'bar'])

b.py

#!/usr/bin/env python2

import sys

print sys.argv

Running ./a.py outputs ['./b.py', 'foo', 'bar'].

You could also try using past.translation instead:

The past module provides an experimental translation package to help with importing and using old Python 2 modules in a Python 3 environment.

chash
  • 3,975
  • 13
  • 29
1

shell=True is only needed if you do something like

subprocess.run("/path/to/sh /path/to/file1 /path/to/file2", shell=True)

where the shell will split the single string into arguments that will identify as the program name and its arguments. But you already have the program name and its arguments identified, so

subprocess.run(['/path/to/sh', '/path/to/file1', '/path/to/file2'])

is all you need.


By using a list and shell=True, you are essentially asking Python to execute

sh -c /path/to/sh /path/to/file1 /path/to/file2

which uses /path/to/file1 to set the value of $0, not $1, in the command to execute.

chepner
  • 497,756
  • 71
  • 530
  • 681