3

The following command works fine from the CLI:

bash <(curl -Ls https://coverage.codacy.com/get.sh) report -r /path/coverage.xml

When I pass the same command to subprocess with shell=False, I get the following error:

FileNotFoundError: [Errno 2] No such file or directory: 'bash <(curl -Ls https://coverage.codacy.com/get.sh) report -r /path/coverage.xml'

with shell=True, I get this error:

/bin/sh: -c: line 0: syntax error near unexpected token `('

To me, it looks like the entire command is being treated as a path when shell is False, and I don't understand why subprocess thinks there is a syntax error when shell=True.

How can I get this command to work from Python?

OneCricketeer
  • 179,855
  • 19
  • 132
  • 245
kravb
  • 417
  • 4
  • 16
  • You should download and execute your script as two separate steps. Input redirection does not work the same with subprocess – OneCricketeer May 13 '22 at 19:34
  • Also, when using just a string, that is the _**path** to an executable_ (thus why you get `FileNotFoundError`) and should not be the full command you want to run. You use a list to run commands with arguments. – OneCricketeer May 13 '22 at 19:36
  • 2
    As the error message shows, shell=True uses `/bin/sh` which is required to be a POSIX-compatible shell (apparently on your system actually bash in POSIX mode). Process substitution is a ksh/bash extension, it is not valid POSIX. – dave_thompson_085 May 13 '22 at 19:44
  • While the linked duplicate is most directly on point, you may also find [bash-style process substitution with Python's Popen()](https://stackoverflow.com/questions/15343447/bash-style-process-substitution-with-pythons-popen) to be of interest -- showing how to get the same effect _without_ `shell=True`. – Charles Duffy May 14 '22 at 13:27

1 Answers1

1

The command you are trying to run requires Bash, but subprocess runs sh unless you tell it otherwise.

p = subprocess.run(
    "bash <(curl -Ls https://coverage.codacy.com/get.sh) report -r /path/coverage.xml",
    shell=True, check=True, text=True,
    executable="/bin/bash")

needlessly runs bash as a subprocess of itself, but gets the job done here and now.

A more efficient solution would avoid the extra shell, but then perhaps you should refactor to replace curl with a simple native Python web client instead.

tripleee
  • 175,061
  • 34
  • 275
  • 318