Why Does Simple Echo in Subprocess Not Working

Why does simple echo in subprocess not working

On Unix shell=True implies that 2nd and following arguments are for the shell itself, use a string to pass a command to the shell:

import subprocess

cmd = 'echo $HOME'
proc = subprocess.Popen(cmd, shell=True, stdout=subprocess.PIPE)
print proc.communicate()[0],

You could also write it as:

import subprocess

cmd = 'echo $HOME'
print subprocess.check_output(cmd, shell=True),

From the subprocess' docs:

On Unix with shell=True, the shell defaults to /bin/sh. If args is a
string, the string specifies the command to execute through the shell.
This means that the string must be formatted exactly as it would be
when typed at the shell prompt. This includes, for example, quoting or
backslash escaping filenames with spaces in them. If args is a
sequence, the first item specifies the command string, and any
additional items will be treated as additional arguments to the shell
itself
. That is to say, Popen does the equivalent of:

Popen(['/bin/sh', '-c', args[0], args[1], ...])

Python: echo with subprocess

you're making heavy use of shell features, mostly by running 2 process piped together.

subprocess.call(shlex.split(command),shell=True)

is a quickfix.

A proper way of doing it would be to use 1 subprocess.Popen instance, provide the input through communicate (to simulate echo python ...) and drop shell=True (using pipes.quote as Charles commented to make sure that the strings are properly quoted if needed)

import pipes
input_string = "python sub_master_script.py {} {}\n".format(*(map(pipes.quote,[str(i),path])))

p = subprocess.Popen(['qsub','-pe','make','5','-N','Teaching_{}'.format(i),'-cwd'],stdin=subprocess.PIPE)
out,err = p.communicate(input_string)

python: why does calling echo with subprocess return WindowsError 2?

The echo command is built in to the Windows shell, cmd.exe. It is not an external program that can be called without the shell. Therefore, your subprocess.call() needs to specify shell=True.

subprocess.call('echo hello', shell=True)

(Also, the shell will handle splitting up the command for you, so I've used the simpler single-string style of passing the command.)

Why is Popen(cmd.exe echo a, shell=True) not running echo?

cmd.exe requires the argument /c to precede a script being passed for execution:

x = subprocess.Popen(["cmd.exe", "/c", "echo a"], stdout=PIPE)
print (x.stdout.read())

subprocess echo $ENVIRONMENT_VAR outputs $ENVIRONMENT_VAR

When you run echo $x from the shell, it is the shell that expands the variable into its value. So if the value of x is 5, for example, the argument that echo receives is 5. It will never know about the variable.

So the solution is to retrieve the value of the environment variable in your python program and pass that value to echo:

import subprocess
import os
echo_arg = os.environ['UPFW_WORK_PATH']
cmd = subprocess.Popen(["echo", echo_arg], stdout=subprocess.PIPE)

What's the difference between subprocess.Popen(echo $HOME... and subprocess.Popen([echo, $HOME]

The first argument to subprocess.Popen() tells the system what to run.

When it is a list, you need to use shell=False. It coincidentally happens to work as you hope in Windows; but on Unix-like platforms, you are simply passing in a number of arguments which will typically get ignored. Effectively,

/bin/sh -c 'echo' '$HOME'

which simply causes the second argument to not be used for anything (where I use single quotes to emphasize that these are just static strings).

In my humble opinion, Python should throw an error in this case. On Windows, too. This is an error which should be caught and reported.

(In the opposite case, where shell=False is specified but the string you pass in is not the name of a valid command, you will get an error eventually anyway, and it makes sense if you have even a vague idea of what's going on.)

If you really know what you are doing, you could cause the first argument to access subsequent arguments; for example

/bin/sh -c 'printf "%s\n" "$@"' 'ick' 'foo' 'bar' 'baz'

would print foo, bar, and baz on separate lines. (The "zeroth" argument - here, 'ick' - is used to populate $0.) But this is just an obscure corollary; don't try to use this for anything.

As a further aside, you should not use subprocess.Popen() if you just want a command to run. The subprocess.run() documentation tells you this in some more detail. With text=True you get a string instead of bytes.

result = subprocess.run('echo "$HOME"', shell=True,
text=True, capture_output=True, check=True)
print(result.stdout, result.stderr)

And of course, os.environ['HOME'] lets you access the value of $HOME from within Python. This also allows you to avoid shell=True which you usually should if you can.

Running batch file with subprocess.call does not work and freezes IPython console

Spyder doesn't always handle standard streams correctly so it doesn't surprise me that you see no output when using subprocess.call because it normally runs in the same console. It also makes sense why it does work for you when executed in an external cmd prompt.

Here is what you should use if you want to keep using the spyder terminal, but call up a new window for your bat script

subprocess.call(["start", "test.bat"], shell=True)

start Starts a separate Command Prompt window to run a specified program or command. You need shell=True because it's a cmd built-in not a program itself. You can then just pass it your bat file as normal.

set echo ON in Python call to Oracle SQL is not working

Its fixed after using SQL file instead of direct commands.

sqlplus = Popen(["sqlplus", "-S", "/", "as", "sysdba", "@file.sql"], stdout=PIPE, stdin=PIPE)



Related Topics



Leave a reply



Submit