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
Python Script Is Not Running Under Cron, Despite Working When Run Manually
Python Requests Json Returns Single Quote
How to Return a Value from a Shell Script in a Python Script
Anaconda Python Not Available from Sudo
Launch Default Image Viewer from Pygtk Program
How to Retrieve the Process Start Time (Or Uptime) in Python
Install Tkinter on Amazon Linux
Determine If Package Installed with Yum Python API
Errors When Trying to Save Command Line Output to a File
What's the Advantage of Queues Over Pipes When Communicating Between Processes
Can Python Detect Which Os Is It Running Under
How to Explicitly Set Carriage Return When Doing JSON.Dump
Accessing Dict Keys Like an Attribute
How to Downgrade My Version of Python from 3.7.5 to 3.6.5 on Ubuntu