Executing a subprocess fails
To execute a batch file in Windows:
from subprocess import Popen
p = Popen("batchfile.bat", cwd=r"c:\directory\containing\batchfile")
stdout, stderr = p.communicate()
If you don't want to execute the batch file, but rather execute the command in your question directly from Python, you need to experiment a bit with the first argument to Popen.
First of all, the first argument can either be a string or a sequence.
So you either write:
p = Popen(r'"C:\Program Files\Systems\Emb Work 5.4\common\bin\run" "C:\Program Files\Systems\Emb Work 5.4\arm\bin\mpr.dll" ... ...', cwd=r"...")
or
p = Popen([r"C:\Program Files\Systems\Emb Work 5.4\common\bin\run", r"C:\Program Files\Systems\Emb Work 5.4\arm\bin\mpr.dll", ...], cwd=r"...")
# ... notice how you don't need to quote the elements containing spaces
According to the documentation:
On Windows: the Popen class uses CreateProcess() to execute the child program, which operates on strings. If args is a sequence, it will be converted to a string using the list2cmdline() method. Please note that not all MS Windows applications interpret the command line the same way: list2cmdline() is designed for applications using the same rules as the MS C runtime.
So if you use a sequence, it will be converted to a string. I would probably try with a sequence first, since then you won't have to quote all the elements that contain spaces (list2cmdline()
does that for you).
For troubleshooting, I recommend you pass your sequence to subprocess.list2cmdline()
and check the output.
Edit:
Here's what I'd do if I were you:
a) Create a simple Python script (testparams.py
) like this:
import subprocess
params = [r"C:\Program Files\Systems\Emb Work 5.4\common\bin\run.exe", ...]
print subprocess.list2cmdline(params)
b) Run the script from the command line (python testparams.py
), copy and paste the output to another command line, press enter and see what happens.
c) If it does not work, edit the python file and repeat until it works.
subprocess.run simple scenario fails
The quoting is wrong, you should have '-f', '1',
etc
How to handle subprocess.run() error/exception
There is no way running cd
in a subprocess is useful. The subprocess will change its own directory and then immediately exit, leaving no observable change in the parent process or anywhere else.
For the same reason, there is no binary command named cd
on most systems; the cd
command is a shell built-in.
Generally, if you run subprocess.run()
without the check=True
keyword argument, any error within the subprocess will simply be ignored. So if /bin/cd
or a similar command existed, you could run
# purely theoretical, and utterly useless
subprocess.run(['cd', UserInput])
and simply not know whether it did anything or not.
If you do supply check=True
, the exception you need to trap is CalledProcessError
:
try:
# pointless code as such; see explanation above
subprocess.run(['cd', UserInput], check=True)
except subprocess.CalledProcessError:
print('Directory name %s misspelled, or you lack the permissions' % UserInput)
But even more fundamentally, allowing users to prod the system by running arbitrary unchecked input in a subprocess is a horrible idea. (Allowing users to run arbitrary shell script with shell=True
is a monumentally, catastrophically horrible idea, so let's not even go there. Maybe see Actual meaning of shell=True
in subprocess
)
A somewhat more secure approach is to run the subprocess with a cwd=
keyword argument.
# also vaguely pointless
subprocess.run(['true'], cwd=UserInput)
In this case, you can expect a regular FileNotFoundError
if the directory does not exist, or a PermissionError
if you lack the privileges.
You should probably still add check=True
and be prepared to handle any resulting exception, unless you specifically don't care whether the subprocess succeeded. (There are actually cases where this makes sense, like when you grep
for something but are fine with it not finding any matches, which raises an error if you use check=True
.)
Perhaps see also Running Bash commands in Python
Running Python script through subprocess fails
Executing ./util.py
in a terminal means "Look in the current working directory for a file named util.py and run it." The working directory is the directory from where you run the command. This means that your python script cannot see util.py if you run it from a different directory.
If you are sure that file1.py and util.py always lie in the same directory, you could use __file__
and os.path.dirname
to prefix it with the directory of file1.py:
file1.py:
#!/usr/bin/env python
import os
import subprocess
current_dir = os.path.dirname(__file__)
filename = os.path.join(current_dir, "util.py")
out = subprocess.Popen([filename], shell=True)
print("done")
How to overcome Type error with subprocess call python3
The issue is that you are trying to split the stdout.PIPE
from the subprocess—a bytes object—using a regular string.
You can either convert the output to a regular string before splitting it (probably what you want):
output = str(rootfs.communicate()[0]).strip().split('\n')
or you can split it using a bytes object:
output = rootfs.communicate()[0].strip().split(b'\n')
Note: you will need to do the same for varfs
and tmPfs
.
subprocess.run() fails at the second iteration
I solved it myself using the plumbum
module.
My codes remained the same, they are all good.
However, I modified the subprocess.run() command, or many of its variants I tried, to be smi = local.cmd.mpirun
, then smi("-n", "1", "../smilei", particular_namelist_name)
and I can run this at every iteration of the loop!
subprocess.run failure vs subprocess.check_call success
The correct execution issubprocess.run(['start', 'npm', 'run', 'features:chrome:server'], check=True)
subprocess.check_call('start npm run features:chrome:server', shell=True)
works because you invoked the shell. Further information you could find here.
subprocess.run("start npm run features:chrome:server", check=True, shell=True)
should also work.
Python script fails execution on subprocess.run() call only when called from context menu
I managed to "solve" the problem by the round about hackish way of creating a batch file that calls the python script command, but this does seem a bit of a hack, and I would think there would be a better way.
Running a subprocess fails when not using pytest no-capture
$ pip install ptyprocess==0.6.0
# test.py
import unittest
from ptyprocess import PtyProcess
class TestCase(unittest.TestCase):
def test(self):
process = PtyProcess.spawn(
["sh", "./has-stdin.sh"]
)
process.wait()
output = process.read().decode("utf-8")
if process.exitstatus:
raise Exception(output.strip("\r\n"))
assert output.strip("\r\n") == 'no'
✅ Runs successfully with -s
:
$ pytest test.py -s
platform linux -- Python 3.7.7, pytest-5.4.3, py-1.9.0, pluggy-0.13.1
rootdir: /Users/maikel/docker/library/postgresql
collected 1 item
test.py .
=========================== 1 passed in 0.60s ===========================
✅ Runs successfully without -s
:
$ pytest test.py
platform linux -- Python 3.7.7, pytest-5.4.3, py-1.9.0, pluggy-0.13.1
rootdir: /Users/maikel/docker/library/postgresql
collected 1 item
test.py .
=========================== 1 passed in 0.60s ===========================
Caveats
- It runs quite a bit slower than
subprocess
(0.60s vs 0.02s in this example) - There is no distinction between
stdout
andstderr
The situation is explained by this diagram:
Source: https://github.com/pexpect/ptyprocess/blob/3931cd4/docs/index.rst
Related Topics
Can a Decorator of an Instance Method Access the Class
Is There a Multi-Dimensional Version of Arange/Linspace in Numpy
Bin Size in Matplotlib (Histogram)
Putting Many Python Pandas Dataframes to One Excel Worksheet
How to Remove Leading Whitespace in Python
Crawling with an Authenticated Session in Scrapy
List of All Available Matplotlib Backends
When Is Not a Good Time to Use Python Generators
Format String Unused Named Arguments
Adding a Particle Effect to My Clicker Game
Iterate Over Individual Bytes in Python 3
Forward Fill Specific Columns in Pandas Dataframe
Web Scraping Dynamic Content with Python
Why Is the Exit Window Button Work But the Exit Button in the Game Does Not Work
Safest Way to Convert Float to Integer in Python
Open Cv Error: (-215) Scn == 3 || Scn == 4 in Function Cvtcolor