Execute a child program in a new process. On POSIX, the class uses
os.execvp()
-like behavior to execute the child program. On Windows,
the class uses the Windows CreateProcess()
function. The arguments to
Popen
are as follows.
args should be a sequence of program arguments or else a single string.
By default, the program to execute is the first item in args if args is
a sequence. If args is a string, the interpretation is
platform-dependent and described below. See the shell and executable
arguments for additional differences from the default behavior. Unless
otherwise stated, it is recommended to pass args as a sequence.
On POSIX, if args is a string, the string is interpreted as the name or
path of the program to execute. However, this can only be done if not
passing arguments to the program.
Note
shlex.split()
can be useful when determining the correct
tokenization for args, especially in complex cases:
>>> import shlex, subprocess >>> command_line = input() /bin/vikings -input eggs.txt -output "spam spam.txt" -cmd "echo '$MONEY'" >>> args = shlex.split(command_line) >>> print(args) ['/bin/vikings', '-input', 'eggs.txt', '-output', 'spam spam.txt', '-cmd', "echo '$MONEY'"] >>> p = subprocess.Popen(args) # Success!
Note in particular that options (such as -input) and arguments (such
as eggs.txt) that are separated by whitespace in the shell go in separate
list elements, while arguments that need quoting or backslash escaping when
used in the shell (such as filenames containing spaces or the echo command
shown above) are single list elements.
On Windows, if args is a sequence, it will be converted to a string in a
manner described in Converting an argument sequence to a string on Windows. This is because
the underlying CreateProcess()
operates on strings.
The shell argument (which defaults to False
) specifies whether to use
the shell as the program to execute. If shell is True
, it is
recommended to pass args as a string rather than as a sequence.
On POSIX 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], ...])
On Windows with shell=True
, the COMSPEC
environment variable
specifies the default shell. The only time you need to specify
shell=True
on Windows is when the command you wish to execute is built
into the shell (e.g. dir or copy). You do not need
shell=True
to run a batch file or console-based executable.
Note
Read the Security Considerations section before using shell=True
.
bufsize will be supplied as the corresponding argument to the
open()
function when creating the stdin/stdout/stderr pipe
file objects:
0
means unbuffered (read and write are one
system call and can return short)1
means line buffered
(only usable ifuniversal_newlines=True
i.e., in a text mode)- any other positive value means use a buffer of approximately that
size - negative bufsize (the default) means the system default of
io.DEFAULT_BUFFER_SIZE will be used.
Changed in version 3.3.1: bufsize now defaults to -1 to enable buffering by default to match the
behavior that most code expects. In versions prior to Python 3.2.4 and
3.3.1 it incorrectly defaulted to 0
which was unbuffered
and allowed short reads. This was unintentional and did not match the
behavior of Python 2 as most code expected.
The executable argument specifies a replacement program to execute. It
is very seldom needed. When shell=False
, executable replaces the
program to execute specified by args. However, the original args is
still passed to the program. Most programs treat the program specified
by args as the command name, which can then be different from the program
actually executed. On POSIX, the args name
becomes the display name for the executable in utilities such as
ps. If shell=True
, on POSIX the executable argument
specifies a replacement shell for the default /bin/sh
.
stdin, stdout and stderr specify the executed program’s standard input,
standard output and standard error file handles, respectively. Valid values
are PIPE
, DEVNULL
, an existing file descriptor (a positive
integer), an existing file object, and None
. PIPE
indicates that a new pipe to the child should be created. DEVNULL
indicates that the special file os.devnull
will be used. With the
default settings of None
, no redirection will occur; the child’s file
handles will be inherited from the parent. Additionally, stderr can be
STDOUT
, which indicates that the stderr data from the applications
should be captured into the same file handle as for stdout.
If preexec_fn is set to a callable object, this object will be called in the
child process just before the child is executed.
(POSIX only)
Warning
The preexec_fn parameter is not safe to use in the presence of threads
in your application. The child process could deadlock before exec is
called.
If you must use it, keep it trivial! Minimize the number of libraries
you call into.
Note
If you need to modify the environment for the child use the env
parameter rather than doing it in a preexec_fn.
The start_new_session parameter can take the place of a previously
common use of preexec_fn to call os.setsid() in the child.
If close_fds is true, all file descriptors except 0
, 1
and
2
will be closed before the child process is executed. (POSIX only).
The default varies by platform: Always true on POSIX. On Windows it is
true when stdin/stdout/stderr are None
, false otherwise.
On Windows, if close_fds is true then no handles will be inherited by the
child process. Note that on Windows, you cannot set close_fds to true and
also redirect the standard handles by setting stdin, stdout or stderr.
Changed in version 3.2: The default for close_fds was changed from False
to
what is described above.
pass_fds is an optional sequence of file descriptors to keep open
between the parent and child. Providing any pass_fds forces
close_fds to be True
. (POSIX only)
New in version 3.2: The pass_fds parameter was added.
If cwd is not None
, the function changes the working directory to
cwd before executing the child. cwd can be a str
and
path-like object. In particular, the function
looks for executable (or for the first item in args) relative to cwd
if the executable path is a relative path.
Changed in version 3.6: cwd parameter accepts a path-like object.
If restore_signals is true (the default) all signals that Python has set to
SIG_IGN are restored to SIG_DFL in the child process before the exec.
Currently this includes the SIGPIPE, SIGXFZ and SIGXFSZ signals.
(POSIX only)
Changed in version 3.2: restore_signals was added.
If start_new_session is true the setsid() system call will be made in the
child process prior to the execution of the subprocess. (POSIX only)
Changed in version 3.2: start_new_session was added.
If env is not None
, it must be a mapping that defines the environment
variables for the new process; these are used instead of the default
behavior of inheriting the current process’ environment.
Note
If specified, env must provide any variables required for the program to
execute. On Windows, in order to run a side-by-side assembly the
specified env must include a valid SystemRoot
.
If encoding or errors are specified, the file objects stdin, stdout
and stderr are opened in text mode with the specified encoding and
errors, as described above in Frequently Used Arguments. If
universal_newlines is True
, they are opened in text mode with default
encoding. Otherwise, they are opened as binary streams.
New in version 3.6: encoding and errors were added.
If given, startupinfo will be a STARTUPINFO
object, which is
passed to the underlying CreateProcess
function.
creationflags, if given, can be one or more of the following flags:
CREATE_NEW_CONSOLE
CREATE_NEW_PROCESS_GROUP
ABOVE_NORMAL_PRIORITY_CLASS
BELOW_NORMAL_PRIORITY_CLASS
HIGH_PRIORITY_CLASS
IDLE_PRIORITY_CLASS
NORMAL_PRIORITY_CLASS
REALTIME_PRIORITY_CLASS
CREATE_NO_WINDOW
DETACHED_PROCESS
CREATE_DEFAULT_ERROR_MODE
CREATE_BREAKAWAY_FROM_JOB
Popen objects are supported as context managers via the with
statement:
on exit, standard file descriptors are closed, and the process is waited for.
with Popen(["ifconfig"], stdout=PIPE) as proc: log.write(proc.stdout.read())
Changed in version 3.2: Added context manager support.
Changed in version 3.6: Popen destructor now emits a ResourceWarning
warning if the child
process is still running.
Содержание:
- Проверка на завершение процесса
Popen.poll()
, - Ожидание завершения процесса
Popen.wait()
, - Взаимодействие с процессом
Popen.communicate()
, - Послать сигнал процессу
Popen.send_signal()
, - Остановить процесс
Popen.terminate()
, - Убить процесс
Popen.kill()
, - Вернуть имя программы со всеми параметрами
Popen.args()
, - Передать данные процессу
Popen.stdin()
, - Извлечь генерируемые данные процессом
Popen.stdout()
, - Извлечь ошибки процесса
Popen.stderr()
, - Посмотреть
pid
процессаPopen.pid()
, - Посмотреть код, с которым завершился процесс
Popen.returncode()
.
Методы объекта Popen
.
Popen.poll()
:
Метод Popen.poll()
проверяет, завершен ли дочерний процесс. Возвращает атрибут кода возврата Popen.returncode
. В противном случае возвращает None
.
>>> import time, subprocess >>> proc = subprocess.Popen(['sleep', '30']) >>> print(proc.poll()) # None # после 30 секунд >>> print(proc.poll()) # 0 >>> proc.returncode # 0
Popen.wait(timeout=None)
:
Метод Popen.wait()
ждет завершения дочернего процесса. Возвращает атрибут кода возврата Popen.returncode
.
>>> import subprocess >>> proc = subprocess.Popen(['sleep', '10']) >>> proc.wait() # 0 >>> proc = subprocess.Popen(['sleep', '10']) >>> proc.wait(5) # Traceback (most recent call last): # raise TimeoutExpired(self.args, timeout) # subprocess.TimeoutExpired: Command '['sleep', '10']' timed out after 5 seconds
Примечание:
- Метод
Popen.wait()
приведет к взаимоблокировке при использованииstdout=subprocess.PIPE
илиstderr=subprocess.PIPE
если дочерний процесс генерирует достаточно данных для канала. Метод блокирует ожидание буфера канала ОС для приема большего количества данных. Используйте методPopen.communicate()
при использовании каналов, чтобы избежать этого. - Метод реализован с использованием цикла занятости (неблокирующий вызов и короткие спящие режимы). Используйте модуль
asyncio
для асинхронного ожидания.
Popen.communicate(input=None, timeout=None)
:
Метод Popen.communicate()
взаимодействует с процессом, отправляя данные в stdin
и читает данные из stdout
и stderr
, пока не будет достигнут конец файла. Необязательным входным аргументом должны быть данные input
, которые будут отправлены дочернему процессу или None
, если никакие данные отправлять не требуется.
Метод Popen.communicate()
возвращает кортеж (stdout_data, stderr_data)
. Данные будут строками, если потоки были открыты в текстовом режиме, в противном случае байты.
>>> from subprocess import Popen, PIPE >>> cmd = ['ls', '-Rla', '/tmp'] >>> proc = Popen(cmd, stdout=PIPE, stderr=PIPE, encoding='utf-8') >>> stdout, stderr = proc.communicate() >>> print(stdout) # /tmp: # итого 76 # drwxrwxrwt 17 root root 4096 мая 13 15:06 . # drwxr-xr-x 26 root root 4096 апр 30 09:18 .. # drwxrwxrwt 2 root root 4096 мая 13 07:35 .font-unix # drwxrwxrwt 2 root root 4096 мая 13 07:35 .ICE-unix # ... # ... >>> print(stderr) # ls: невозможно открыть каталог ... Отказано в доступе # ls: невозможно открыть каталог ... Отказано в доступе # ... # ...
, что если необходимо отправить данные в процесс, то нужно создать вызвать subprocess.Popen()
с аргументом stdin=subprocess.PIPE
. Точно так же, чтобы получить что-то кроме None
в кортеже результата, то также нужно указать stdout=subprocess.PIPE
и/или stderr=subprocess.PIPE
.
Если истекает время ожидания timeout
, то дочерний процесс не уничтожается, поэтому для правильной очистки, приложение с хорошим поведением должно завершить дочерний процесс и завершить соединение:
# псевдокод proc = subprocess.Popen(...) try: outs, errs = proc.communicate(timeout=15) except TimeoutExpired: proc.kill() outs, errs = proc.communicate()
Примечание:
- Считываемые данные буферизируются в памяти, поэтому не используйте этот метод, если размер данных большой или неограниченный. В этом случае пишите данные в лог-файл, пример смотрите в разделе «Часто используемые параметры модуля
subprocess
«.
Popen.send_signal(signal)
:
Метод Popen.send_signal()
посылает сигнал signal
дочернему процессу.
>>> import subprocess >>> proc = subprocess.Popen(['sleep', '60']) >>> proc.send_signal(9) >>> proc.poll() # -9
Примечание:
- В Windows
SIGTERM
является псевдонимомPopen.terminate()
.CTRL_C_EVENT
иCTRL_BREAK_EVENT
можно отправлять процессам, запущенным с параметромcreationflags
, который включаетCREATE_NEW_PROCESS_GROUP
.
Popen.terminate()
:
Метод Popen.terminate()
останавливает дочерний процесс.
- В ОС Unix метод отправляет
SIGTERM
дочернему процессу. - В Windows вызывается Win32 API-функция
TerminateProcess()
.
>>> import subprocess >>> proc = subprocess.Popen(['sleep', '60']) >>> proc.terminate() >>> proc.poll() # -15
Popen.kill()
:
Метод Popen.kill()
убивает дочерний процесс.
- В ОС Unix функция отправляет
SIGKILL
ребенку. - В Windows метод
Popen.kill()
является псевдонимомPopen.terminate()
.
>>> import subprocess >>> proc = subprocess.Popen(['sleep', '60']) >>> proc.kill() >>> proc.poll() -9
Атрибуты объекта Popen
.
Popen.args
:
Атрибут Popen.args()
возвращает аргумент args
в том виде, как он был передан в subprocess.Popen()
. Представляет из себя список аргументов программы или отдельная строка.
Popen.stdin
:
Если аргумент stdin=subprocess.PIPE
, то атрибут Popen.stdin()
является записываемым объектом потока, возвращаемым функцией open()
.
Если были заданы аргументы encoding
или errors
, или text=True
(также известный как universal_newlines), то Popen.stdin()
является текстовым потоком, в противном случае это поток байтов.
Если аргумент stdin
не был равен subprocess.PIPE
, то этот атрибут будет возвращать None
.
Предупреждение:
- Используйте метод
Popen.communicate()
вместо методовPopen.stdin.write()
, чтобы избежать взаимных блокировок из-за того, что другие буферы конвейера ОС заполняют и блокируют дочерний процесс.
Popen.stdout
:
Если аргумент stdout=subprocess.PIPE
, то атрибут Popen.stdout()
является читаемым объектом потока, возвращаемым функцией open()
. Чтение из потока stdout
обеспечивает вывод генерируемых данных от дочернего процесса.
Если были заданы аргументы encoding
или errors
, или text=True
(также известный как universal_newlines), то Popen.stdout()
является текстовым потоком, в противном случае это поток байтов.
Если аргумент stdout
не был равен subprocess.PIPE
, то этот атрибут будет возвращать None
.
Предупреждение:
- Используйте метод
Popen.communicate()
вместо методаPopen.stdout.read()
, чтобы избежать взаимных блокировок из-за того, что другие буферы конвейера ОС заполняют и блокируют дочерний процесс.
Popen.stderr
:
Если аргумент stderr=subprocess.PIPE
, то атрибут Popen.stderr()
является читаемым объектом потока, возвращаемым open (). Чтение из потока stderr
обеспечивает вывод ошибок от дочернего процесса.
Если были заданы аргументы encoding
или errors
, или text=True
(также известный как universal_newlines), то Popen.stderr()
является текстовым потоком, в противном случае это поток байтов.
Если аргумент stderr
не был равен subprocess.PIPE
, то этот атрибут будет возвращать None
.
Предупреждение:
- Используйте метод
Popen.communicate()
вместо методаPopen.stderr.read()
, чтобы избежать взаимных блокировок из-за того, что другие буферы конвейера ОС заполняют и блокируют дочерний процесс.
Popen.pid
:
Атрибут Popen.pid()
возвращает идентификатор ID процесса дочернего процесса.
>>> import subprocess >>> proc = subprocess.Popen(['sleep', '10']) >>> proc.pid # 6016
, что если аргумент shell=True
, то это идентификатор процесса порожденный оболочкой.
Popen.returncode
:
Атрибут Popen.returncode()
это код возврата дочернего процесса, установленный Popen.poll()
и Popen.wait()
и косвенно — Popen.communicate()
. Значение None
указывает, что процесс еще не завершен.
Отрицательное значение -N
указывает на то, что дочерний элемент был прерван сигналом N
. Справедливо только для Unix.
>>> import subprocess >>> proc = subprocess.Popen(['sleep', '20']) >>> print(proc.returncode) # None >>> proc.terminate() >>> proc.poll() # -15 >>> proc.returncode # -15
Purpose: | Spawn and communicate with additional processes. |
---|---|
Available In: | 2.4 and later |
The subprocess module provides a consistent interface to
creating and working with additional processes. It offers a
higher-level interface than some of the other available modules, and
is intended to replace functions such as os.system(),
os.spawn*(), os.popen*(), popen2.*() and
commands.*(). To make it easier to compare subprocess
with those other modules, many of the examples here re-create the ones
used for os and popen.
The subprocess module defines one class, Popen and a
few wrapper functions that use that class. The constructor for
Popen takes arguments to set up the new process so the parent
can communicate with it via pipes. It provides all of the
functionality of the other modules and functions it replaces, and
more. The API is consistent for all uses, and many of the extra steps
of overhead needed (such as closing extra file descriptors and
ensuring the pipes are closed) are “built in” instead of being handled
by the application code separately.
Note
The API is roughly the same, but the underlying implementation is
slightly different between Unix and Windows. All of the examples
shown here were tested on Mac OS X. Behavior on a non-Unix OS will
vary.
Running External Command¶
To run an external command without interacting with it, such as one
would do with os.system(), Use the call()
function.
import subprocess # Simple command subprocess.call(['ls', '-1'], shell=True)
The command line arguments are passed as a list of strings, which
avoids the need for escaping quotes or other special characters that
might be interpreted by the shell.
$ python subprocess_os_system.py __init__.py index.rst interaction.py repeater.py signal_child.py signal_parent.py subprocess_check_call.py subprocess_check_output.py subprocess_check_output_error.py subprocess_check_output_error_trap_output.py subprocess_os_system.py subprocess_pipes.py subprocess_popen2.py subprocess_popen3.py subprocess_popen4.py subprocess_popen_read.py subprocess_popen_write.py subprocess_shell_variables.py subprocess_signal_parent_shell.py subprocess_signal_setsid.py
Setting the shell argument to a true value causes subprocess
to spawn an intermediate shell process, and tell it to run the
command. The default is to run the command directly.
import subprocess # Command with shell expansion subprocess.call('echo $HOME', shell=True)
Using an intermediate shell means that variables, glob patterns, and
other special shell features in the command string are processed
before the command is run.
$ python subprocess_shell_variables.py /Users/dhellmann
Error Handling¶
The return value from call() is the exit code of the program.
The caller is responsible for interpreting it to detect errors. The
check_call() function works like call() except that the
exit code is checked, and if it indicates an error happened then a
CalledProcessError exception is raised.
import subprocess subprocess.check_call(['false'])
The false command always exits with a non-zero status code,
which check_call() interprets as an error.
$ python subprocess_check_call.py Traceback (most recent call last): File "subprocess_check_call.py", line 11, in <module> subprocess.check_call(['false']) File "/Library/Frameworks/Python.framework/Versions/2.7/lib/python2. 7/subprocess.py", line 511, in check_call raise CalledProcessError(retcode, cmd) subprocess.CalledProcessError: Command '['false']' returned non-zero e xit status 1
Capturing Output¶
The standard input and output channels for the process started by
call() are bound to the parent’s input and output. That means
the calling programm cannot capture the output of the command. Use
check_output() to capture the output for later processing.
import subprocess output = subprocess.check_output(['ls', '-1']) print 'Have %d bytes in output' % len(output) print output
The ls -1 command runs successfully, so the text it prints to
standard output is captured and returned.
$ python subprocess_check_output.py Have 462 bytes in output __init__.py index.rst interaction.py repeater.py signal_child.py signal_parent.py subprocess_check_call.py subprocess_check_output.py subprocess_check_output_error.py subprocess_check_output_error_trap_output.py subprocess_os_system.py subprocess_pipes.py subprocess_popen2.py subprocess_popen3.py subprocess_popen4.py subprocess_popen_read.py subprocess_popen_write.py subprocess_shell_variables.py subprocess_signal_parent_shell.py subprocess_signal_setsid.py
This script runs a series of commands in a subshell. Messages are
sent to standard output and standard error before the commands exit
with an error code.
import subprocess output = subprocess.check_output( 'echo to stdout; echo to stderr 1>&2; exit 1', shell=True, ) print 'Have %d bytes in output' % len(output) print output
The message to standard error is printed to the console, but the
message to standard output is hidden.
$ python subprocess_check_output_error.py to stderr Traceback (most recent call last): File "subprocess_check_output_error.py", line 14, in <module> shell=True, File "/Library/Frameworks/Python.framework/Versions/2.7/lib/python2. 7/subprocess.py", line 544, in check_output raise CalledProcessError(retcode, cmd, output=output) subprocess.CalledProcessError: Command 'echo to stdout; echo to stderr 1>&2; exit 1' returned non-zero exit status 1
To prevent error messages from commands run through
check_output() from being written to the console, set the
stderr parameter to the constant STDOUT.
import subprocess output = subprocess.check_output( 'echo to stdout; echo to stderr 1>&2; exit 1', shell=True, stderr=subprocess.STDOUT, ) print 'Have %d bytes in output' % len(output) print output
Now the error and standard output channels are merged together so if
the command prints error messages, they are captured and not sent to
the console.
$ python subprocess_check_output_error_trap_output.py Traceback (most recent call last): File "subprocess_check_output_error_trap_output.py", line 15, in <mo dule> stderr=subprocess.STDOUT, File "/Library/Frameworks/Python.framework/Versions/2.7/lib/python2. 7/subprocess.py", line 544, in check_output raise CalledProcessError(retcode, cmd, output=output) subprocess.CalledProcessError: Command 'echo to stdout; echo to stderr 1>&2; exit 1' returned non-zero exit status 1
Working with Pipes Directly¶
By passing different arguments for stdin, stdout, and stderr it
is possible to mimic the variations of os.popen().
popen¶
To run a process and read all of its output, set the stdout value to
PIPE and call communicate().
import subprocess print 'nread:' proc = subprocess.Popen(['echo', '"to stdout"'], stdout=subprocess.PIPE, ) stdout_value = proc.communicate()[0] print 'tstdout:', repr(stdout_value)
This is similar to the way popen() works, except that the
reading is managed internally by the Popen instance.
$ python subprocess_popen_read.py read: stdout: '"to stdout"n'
To set up a pipe to allow the calling program to write data to it, set
stdin to PIPE.
import subprocess print 'nwrite:' proc = subprocess.Popen(['cat', '-'], stdin=subprocess.PIPE, ) proc.communicate('tstdin: to stdinn')
To send data to the standard input channel of the process one time,
pass the data to communicate(). This is similar to using
popen() with mode ‘w’.
$ python -u subprocess_popen_write.py write: stdin: to stdin
popen2¶
To set up the Popen instance for reading and writing, use a
combination of the previous techniques.
import subprocess print 'npopen2:' proc = subprocess.Popen(['cat', '-'], stdin=subprocess.PIPE, stdout=subprocess.PIPE, ) stdout_value = proc.communicate('through stdin to stdout')[0] print 'tpass through:', repr(stdout_value)
This sets up the pipe to mimic popen2().
$ python -u subprocess_popen2.py popen2: pass through: 'through stdin to stdout'
popen3¶
It is also possible watch both of the streams for stdout and stderr,
as with popen3().
import subprocess print 'npopen3:' proc = subprocess.Popen('cat -; echo "to stderr" 1>&2', shell=True, stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE, ) stdout_value, stderr_value = proc.communicate('through stdin to stdout') print 'tpass through:', repr(stdout_value) print 'tstderr :', repr(stderr_value)
Reading from stderr works the same as with stdout. Passing
PIPE tells Popen to attach to the channel, and
communicate() reads all of the data from it before returning.
$ python -u subprocess_popen3.py popen3: pass through: 'through stdin to stdout' stderr : 'to stderrn'
popen4¶
To direct the error output from the process to its standard output
channel, use STDOUT for stderr instead of PIPE.
import subprocess print 'npopen4:' proc = subprocess.Popen('cat -; echo "to stderr" 1>&2', shell=True, stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.STDOUT, ) stdout_value, stderr_value = proc.communicate('through stdin to stdoutn') print 'tcombined output:', repr(stdout_value) print 'tstderr value :', repr(stderr_value)
Combining the output in this way is similar to how popen4()
works.
$ python -u subprocess_popen4.py popen4: combined output: 'through stdin to stdoutnto stderrn' stderr value : None
Connecting Segments of a Pipe¶
Multiple commands can be connected into a pipeline, similar to the
way the Unix shell works, by creating separate Popen
instances and chaining their inputs and outputs together. The
stdout attribute of one Popen instance is used as the
stdin argument for the next in the pipeline, instead of the constant
PIPE. The output is read from the stdout handle for
the final command in the pipeline.
import subprocess cat = subprocess.Popen(['cat', 'index.rst'], stdout=subprocess.PIPE, ) grep = subprocess.Popen(['grep', '.. include::'], stdin=cat.stdout, stdout=subprocess.PIPE, ) cut = subprocess.Popen(['cut', '-f', '3', '-d:'], stdin=grep.stdout, stdout=subprocess.PIPE, ) end_of_pipe = cut.stdout print 'Included files:' for line in end_of_pipe: print 't', line.strip()
This example reproduces the command line cat index.rst | grep
«.. include» | cut -f 3 -d:, which reads the reStructuredText source
file for this section and finds all of the lines that include other
files, then prints only the filenames.
$ python -u subprocess_pipes.py Included files: subprocess_os_system.py subprocess_shell_variables.py subprocess_check_call.py subprocess_check_output.py subprocess_check_output_error.py subprocess_check_output_error_trap_output.py subprocess_popen_read.py subprocess_popen_write.py subprocess_popen2.py subprocess_popen3.py subprocess_popen4.py subprocess_pipes.py repeater.py interaction.py signal_child.py signal_parent.py subprocess_signal_parent_shell.py subprocess_signal_setsid.py
Interacting with Another Command¶
All of the above examples assume a limited amount of interaction. The
communicate() method reads all of the output and waits for
child process to exit before returning. It is also possible to write
to and read from the individual pipe handles used by the
Popen instance. A simple echo program that reads from
standard input and writes to standard output illustrates this:
import sys sys.stderr.write('repeater.py: startingn') sys.stderr.flush() while True: next_line = sys.stdin.readline() if not next_line: break sys.stdout.write(next_line) sys.stdout.flush() sys.stderr.write('repeater.py: exitingn') sys.stderr.flush()
The script, repeater.py, writes to stderr when it starts and
stops. That information can be used to show the lifetime of the child
process.
The next interaction example uses the stdin and stdout file handles
owned by the Popen instance in different ways. In the first
example, a sequence of 10 numbers are written to stdin of the process,
and after each write the next line of output is read back. In the
second example, the same 10 numbers are written but the output is read
all at once using communicate().
import subprocess print 'One line at a time:' proc = subprocess.Popen('python repeater.py', shell=True, stdin=subprocess.PIPE, stdout=subprocess.PIPE, ) for i in range(10): proc.stdin.write('%dn' % i) output = proc.stdout.readline() print output.rstrip() remainder = proc.communicate()[0] print remainder print print 'All output at once:' proc = subprocess.Popen('python repeater.py', shell=True, stdin=subprocess.PIPE, stdout=subprocess.PIPE, ) for i in range(10): proc.stdin.write('%dn' % i) output = proc.communicate()[0] print output
The «repeater.py: exiting» lines come at different points in the
output for each loop style.
$ python -u interaction.py One line at a time: repeater.py: starting 0 1 2 3 4 5 6 7 8 9 repeater.py: exiting All output at once: repeater.py: starting repeater.py: exiting 0 1 2 3 4 5 6 7 8 9
Signaling Between Processes¶
The os examples include a demonstration of signaling
between processes using os.fork() and os.kill(). Since each Popen instance
provides a pid attribute with the process id of the child process,
it is possible to do something similar with subprocess. For
example, using this script for the child process to be executed by the
parent process
import os import signal import time import sys pid = os.getpid() received = False def signal_usr1(signum, frame): "Callback invoked when a signal is received" global received received = True print 'CHILD %6s: Received USR1' % pid sys.stdout.flush() print 'CHILD %6s: Setting up signal handler' % pid sys.stdout.flush() signal.signal(signal.SIGUSR1, signal_usr1) print 'CHILD %6s: Pausing to wait for signal' % pid sys.stdout.flush() time.sleep(3) if not received: print 'CHILD %6s: Never received signal' % pid
combined with this parent process
import os import signal import subprocess import time import sys proc = subprocess.Popen(['python', 'signal_child.py']) print 'PARENT : Pausing before sending signal...' sys.stdout.flush() time.sleep(1) print 'PARENT : Signaling child' sys.stdout.flush() os.kill(proc.pid, signal.SIGUSR1)
the output is:
$ python signal_parent.py PARENT : Pausing before sending signal... CHILD 14756: Setting up signal handler CHILD 14756: Pausing to wait for signal PARENT : Signaling child CHILD 14756: Received USR1
Process Groups / Sessions¶
Because of the way the process tree works under Unix, if the process
created by Popen spawns sub-processes, those children will not
receive any signals sent to the parent. That means, for example, it
will be difficult to cause them to terminate by sending
SIGINT or SIGTERM.
import os import signal import subprocess import tempfile import time import sys script = '''#!/bin/sh echo "Shell script in process $$" set -x python signal_child.py ''' script_file = tempfile.NamedTemporaryFile('wt') script_file.write(script) script_file.flush() proc = subprocess.Popen(['sh', script_file.name], close_fds=True) print 'PARENT : Pausing before sending signal to child %s...' % proc.pid sys.stdout.flush() time.sleep(1) print 'PARENT : Signaling child %s' % proc.pid sys.stdout.flush() os.kill(proc.pid, signal.SIGUSR1) time.sleep(3)
The pid used to send the signal does not match the pid of the child of
the shell script waiting for the signal because in this example, there
are three separate processes interacting:
- subprocess_signal_parent_shell.py
- The Unix shell process running the script created by the main python
program. - signal_child.py
$ python subprocess_signal_parent_shell.py PARENT : Pausing before sending signal to child 14759... Shell script in process 14759 + python signal_child.py CHILD 14760: Setting up signal handler CHILD 14760: Pausing to wait for signal PARENT : Signaling child 14759 CHILD 14760: Never received signal
The solution to this problem is to use a process group to associate
the children so they can be signaled together. The process group is
created with os.setsid(), setting the “session id” to the
process id of the current process. All child processes inherit the
session id, and since it should only be set set in the shell created
by Popen and its descendants, os.setsid() should not be
called in the parent process. Instead, the function is passed to
Popen as the preexec_fn argument so it is run after the
fork() inside the new process, before it uses exec() to
run the shell.
import os import signal import subprocess import tempfile import time import sys script = '''#!/bin/sh echo "Shell script in process $$" set -x python signal_child.py ''' script_file = tempfile.NamedTemporaryFile('wt') script_file.write(script) script_file.flush() proc = subprocess.Popen(['sh', script_file.name], close_fds=True, preexec_fn=os.setsid, ) print 'PARENT : Pausing before sending signal to child %s...' % proc.pid sys.stdout.flush() time.sleep(1) print 'PARENT : Signaling process group %s' % proc.pid sys.stdout.flush() os.killpg(proc.pid, signal.SIGUSR1) time.sleep(3)
The sequence of events is:
- The parent program instantiates Popen.
- The Popen instance forks a new process.
- The new process runs os.setsid().
- The new process runs exec() to start the shell.
- The shell runs the shell script.
- The shell script forks again and that process execs Python.
- Python runs signal_child.py.
- The parent program signals the process group using the pid of the shell.
- The shell and Python processes receive the signal. The shell
ignores it. Python invokes the signal handler.
To signal the entire process group, use os.killpg() with the pid
value from the Popen instance.
$ python subprocess_signal_setsid.py PARENT : Pausing before sending signal to child 14763... Shell script in process 14763 + python signal_child.py CHILD 14764: Setting up signal handler CHILD 14764: Pausing to wait for signal PARENT : Signaling process group 14763 CHILD 14764: Received USR1
See also
- subprocess
- Standard library documentation for this module.
- os
- Although many are deprecated, the functions for working with processes
found in the os module are still widely used in existing code. - UNIX SIgnals and Process Groups
- A good description of UNIX signaling and how process groups work.
- Advanced Programming in the UNIX(R) Environment
- Covers working with multiple processes, such as handling signals, closing duplicated
file descriptors, etc. - pipes
- Unix shell command pipeline templates in the standard library.
Exceptions raised in the child process, before the new program has started to execute, will be re-raised in the parent.
The most common exception raised is OSError
. This occurs, for example, when trying to execute a non-existent file. Applications should prepare for OSError
exceptions. Note that, when shell=True
, OSError
will be raised by the child only if the selected shell itself was not found. To determine if the shell failed to find the requested application, it is necessary to check the return code or output from the subprocess.
A ValueError
will be raised if Popen
is called with invalid arguments.
check_call()
and check_output()
will raise CalledProcessError
if the called process returns a non-zero return code.
All of the functions and methods that accept a timeout parameter, such as call()
and Popen.communicate()
will raise TimeoutExpired
if the timeout expires before the process exits.
Exceptions defined in this module all inherit from SubprocessError
.
New in version 3.3: The SubprocessError
base class was added.
Security Considerations
Unlike some other popen functions, this implementation will never implicitly call a system shell. This means that all characters, including shell metacharacters, can safely be passed to child processes. If the shell is invoked explicitly, via shell=True
, it is the application’s responsibility to ensure that all whitespace and metacharacters are quoted appropriately to avoid shell injection vulnerabilities. On some platforms, it is possible to use shlex.quote()
for this escaping.
Popen Objects
Instances of the Popen
class have the following methods:
-
Popen.poll()
-
Check if child process has terminated. Set and return
returncode
attribute. Otherwise, returnsNone
.
-
Popen.wait(timeout=None)
-
Wait for child process to terminate. Set and return
returncode
attribute.If the process does not terminate after timeout seconds, raise a
TimeoutExpired
exception. It is safe to catch this exception and retry the wait.Note
This will deadlock when using
stdout=PIPE
orstderr=PIPE
and the child process generates enough output to a pipe such that it blocks waiting for the OS pipe buffer to accept more data. UsePopen.communicate()
when using pipes to avoid that.Changed in version 3.3: timeout was added.
-
Popen.communicate(input=None, timeout=None)
-
Interact with process: Send data to stdin. Read data from stdout and stderr, until end-of-file is reached. Wait for process to terminate and set the
returncode
attribute. The optional input argument should be data to be sent to the child process, orNone
, if no data should be sent to the child. If streams were opened in text mode, input must be a string. Otherwise, it must be bytes.communicate()
returns a tuple(stdout_data, stderr_data)
. The data will be strings if streams were opened in text mode; otherwise, bytes.Note that if you want to send data to the process’s stdin, you need to create the Popen object with
stdin=PIPE
. Similarly, to get anything other thanNone
in the result tuple, you need to givestdout=PIPE
and/orstderr=PIPE
too.If the process does not terminate after timeout seconds, a
TimeoutExpired
exception will be raised. Catching this exception and retrying communication will not lose any output.The child process is not killed if the timeout expires, so in order to cleanup properly a well-behaved application should kill the child process and finish communication:
proc = subprocess.Popen(...) try: outs, errs = proc.communicate(timeout=15) except TimeoutExpired: proc.kill() outs, errs = proc.communicate()
Note
The data read is buffered in memory, so do not use this method if the data size is large or unlimited.
Changed in version 3.3: timeout was added.
-
Popen.send_signal(signal)
-
Sends the signal signal to the child.
Do nothing if the process completed.
Note
On Windows, SIGTERM is an alias for
terminate()
. CTRL_C_EVENT and CTRL_BREAK_EVENT can be sent to processes started with a creationflags parameter which includesCREATE_NEW_PROCESS_GROUP
.
-
Popen.terminate()
-
Stop the child. On POSIX OSs the method sends SIGTERM to the child. On Windows the Win32 API function
TerminateProcess()
is called to stop the child.
-
Popen.kill()
-
Kills the child. On POSIX OSs the function sends SIGKILL to the child. On Windows
kill()
is an alias forterminate()
.
The following attributes are also available:
-
Popen.args
-
The args argument as it was passed to
Popen
– a sequence of program arguments or else a single string.New in version 3.3.
-
Popen.stdin
-
If the stdin argument was
PIPE
, this attribute is a writeable stream object as returned byopen()
. If the encoding or errors arguments were specified or the universal_newlines argument wasTrue
, the stream is a text stream, otherwise it is a byte stream. If the stdin argument was notPIPE
, this attribute isNone
.
-
Popen.stdout
-
If the stdout argument was
PIPE
, this attribute is a readable stream object as returned byopen()
. Reading from the stream provides output from the child process. If the encoding or errors arguments were specified or the universal_newlines argument wasTrue
, the stream is a text stream, otherwise it is a byte stream. If the stdout argument was notPIPE
, this attribute isNone
.
-
Popen.stderr
-
If the stderr argument was
PIPE
, this attribute is a readable stream object as returned byopen()
. Reading from the stream provides error output from the child process. If the encoding or errors arguments were specified or the universal_newlines argument wasTrue
, the stream is a text stream, otherwise it is a byte stream. If the stderr argument was notPIPE
, this attribute isNone
.
-
Popen.pid
-
The process ID of the child process.
Note that if you set the shell argument to
True
, this is the process ID of the spawned shell.
-
Popen.returncode
-
The child return code, set by
poll()
andwait()
(and indirectly bycommunicate()
). ANone
value indicates that the process hasn’t terminated yet.A negative value
-N
indicates that the child was terminated by signalN
(POSIX only).
Windows Popen Helpers
The STARTUPINFO
class and following constants are only available on Windows.
-
class subprocess.STARTUPINFO(*, dwFlags=0, hStdInput=None, hStdOutput=None, hStdError=None, wShowWindow=0, lpAttributeList=None)
-
Partial support of the Windows STARTUPINFO structure is used for
Popen
creation. The following attributes can be set by passing them as keyword-only arguments.Changed in version 3.7: Keyword-only argument support was added.
-
dwFlags
-
A bit field that determines whether certain
STARTUPINFO
attributes are used when the process creates a window.si = subprocess.STARTUPINFO() si.dwFlags = subprocess.STARTF_USESTDHANDLES | subprocess.STARTF_USESHOWWINDOW
-
hStdInput
-
If
dwFlags
specifiesSTARTF_USESTDHANDLES
, this attribute is the standard input handle for the process. IfSTARTF_USESTDHANDLES
is not specified, the default for standard input is the keyboard buffer.
-
hStdOutput
-
If
dwFlags
specifiesSTARTF_USESTDHANDLES
, this attribute is the standard output handle for the process. Otherwise, this attribute is ignored and the default for standard output is the console window’s buffer.
-
hStdError
-
If
dwFlags
specifiesSTARTF_USESTDHANDLES
, this attribute is the standard error handle for the process. Otherwise, this attribute is ignored and the default for standard error is the console window’s buffer.
-
wShowWindow
-
If
dwFlags
specifiesSTARTF_USESHOWWINDOW
, this attribute can be any of the values that can be specified in thenCmdShow
parameter for the ShowWindow function, except forSW_SHOWDEFAULT
. Otherwise, this attribute is ignored.SW_HIDE
is provided for this attribute. It is used whenPopen
is called withshell=True
.
-
lpAttributeList
-
A dictionary of additional attributes for process creation as given in
STARTUPINFOEX
, see UpdateProcThreadAttribute.Supported attributes:
- handle_list
-
Sequence of handles that will be inherited. close_fds must be true if non-empty.
The handles must be temporarily made inheritable by
os.set_handle_inheritable()
when passed to thePopen
constructor, elseOSError
will be raised with Windows errorERROR_INVALID_PARAMETER
(87).Warning
In a multithreaded process, use caution to avoid leaking handles that are marked inheritable when combining this feature with concurrent calls to other process creation functions that inherit all handles such as
os.system()
. This also applies to standard handle redirection, which temporarily creates inheritable handles.
New in version 3.7.
-
Windows Constants
The subprocess
module exposes the following constants.
-
subprocess.STD_INPUT_HANDLE
-
The standard input device. Initially, this is the console input buffer,
CONIN$
.
-
subprocess.STD_OUTPUT_HANDLE
-
The standard output device. Initially, this is the active console screen buffer,
CONOUT$
.
-
subprocess.STD_ERROR_HANDLE
-
The standard error device. Initially, this is the active console screen buffer,
CONOUT$
.
-
subprocess.SW_HIDE
-
Hides the window. Another window will be activated.
-
subprocess.STARTF_USESTDHANDLES
-
Specifies that the
STARTUPINFO.hStdInput
,STARTUPINFO.hStdOutput
, andSTARTUPINFO.hStdError
attributes contain additional information.
-
subprocess.STARTF_USESHOWWINDOW
-
Specifies that the
STARTUPINFO.wShowWindow
attribute contains additional information.
-
subprocess.CREATE_NEW_CONSOLE
-
The new process has a new console, instead of inheriting its parent’s console (the default).
-
subprocess.CREATE_NEW_PROCESS_GROUP
-
A
Popen
creationflags
parameter to specify that a new process group will be created. This flag is necessary for usingos.kill()
on the subprocess.This flag is ignored if
CREATE_NEW_CONSOLE
is specified.
-
subprocess.ABOVE_NORMAL_PRIORITY_CLASS
-
A
Popen
creationflags
parameter to specify that a new process will have an above average priority.New in version 3.7.
-
subprocess.BELOW_NORMAL_PRIORITY_CLASS
-
A
Popen
creationflags
parameter to specify that a new process will have a below average priority.New in version 3.7.
-
subprocess.HIGH_PRIORITY_CLASS
-
A
Popen
creationflags
parameter to specify that a new process will have a high priority.New in version 3.7.
-
subprocess.IDLE_PRIORITY_CLASS
-
A
Popen
creationflags
parameter to specify that a new process will have an idle (lowest) priority.New in version 3.7.
-
subprocess.NORMAL_PRIORITY_CLASS
-
A
Popen
creationflags
parameter to specify that a new process will have an normal priority. (default)New in version 3.7.
-
subprocess.REALTIME_PRIORITY_CLASS
-
A
Popen
creationflags
parameter to specify that a new process will have realtime priority. You should almost never use REALTIME_PRIORITY_CLASS, because this interrupts system threads that manage mouse input, keyboard input, and background disk flushing. This class can be appropriate for applications that “talk” directly to hardware or that perform brief tasks that should have limited interruptions.New in version 3.7.
-
subprocess.CREATE_NO_WINDOW
-
A
Popen
creationflags
parameter to specify that a new process will not create a window.New in version 3.7.
-
subprocess.DETACHED_PROCESS
-
A
Popen
creationflags
parameter to specify that a new process will not inherit its parent’s console. This value cannot be used with CREATE_NEW_CONSOLE.New in version 3.7.
-
subprocess.CREATE_DEFAULT_ERROR_MODE
-
A
Popen
creationflags
parameter to specify that a new process does not inherit the error mode of the calling process. Instead, the new process gets the default error mode. This feature is particularly useful for multithreaded shell applications that run with hard errors disabled.New in version 3.7.
-
subprocess.CREATE_BREAKAWAY_FROM_JOB
-
A
Popen
creationflags
parameter to specify that a new process is not associated with the job.New in version 3.7.
© 2001–2022 Python Software Foundation
Licensed under the PSF License.
https://docs.python.org/3.11/library/subprocess.html
Python
3.11
-
subprocess — Subprocess management
Source code: Lib/subprocess.py The subprocess module allows you to spawn new processes, connect their input/output/error pipes, and obtain return codes.
-
Popen Constructor
The underlying process creation and management this module handled by Popen class.
-
Older high-level API
Prior to Python 3.5, these three functions comprised high level API subprocess.
-
symtable — Access to the compiler’s symbol tables
Source code: Lib/symtable.py Symbol tables are generated by the compiler from AST just before bytecode is Return the toplevel SymbolTable for Python source
I am a beginner at python coding.
I wrote a simple code that lists a number of programs and asks the user to choose one of the programs. It will then open a website with the version history of that program, and, where it exists, run the updater of the program.
Initially I wrote the program manually writing out the list of programs (20) and then manually write out the url and, where relevant, the path and file name to the updater. Something like:
if choice == 1 url = 'https://blablabla' prg = 'C:\Program Files\blablabla'
After manually defining the URL and prg variables for all 20 options, I run:
webbrowser.open_new_tab(url) subprocess.Popen(prg)
This works fine.
Then I tried to write the code where the list of programs and the url and file paths are listed in a .csv file. The values for the url and prg variables are read from the .csv file (using numpy load.txt)
webbrowser.open_new_tab(url)
works fine
However:
subprocess.Popen(prg)
gives an error message if the file path has a blank space in it (which is in 19 out of the 20 options). The error message is:
Error:
Traceback (most recent call last):
File "test.py", line 32, in <module>
mainmenu()
File "test.py", line 30, in mainmenu
subprocess.Popen(prg)
File "C:UserszorinAppDataLocalProgramsPythonPython38libsubprocess.py", line 858, in _init__
self._execute_child(args, executable, preexec_fn, close_fds,
File "C:UserszorinAppDataLocalProgramsPythonPython38libsubprocess.py", line 1311, in _execute_child
hp, ht, pid, tid = _winapi.CreateProcess(executable, args,
FileNotFoundError: [WinError 2] The system cannot find the file specified
One example:
In the original (long-winded)code I manually set the full file name for Chrome:
prg = 'C:\Program Files\Google\Chrome\Application\chrome.exe'
and
subprocess.Popen(prg)
runs Chrome without a problem.
In the updated code the same full file name is read into prg, but this time
subprocess.Popen(prg)
gives the above-mentioned error code (if the file path has a black space it).
In the new code
print(prg)
will give:
Output:
C:\Program Files\Google\Chrome\Application\chrome.exe
so the correct value is read into the variable.
Any suggestions what I am doing wrong?
I use Windows
Posts: 3,889
Threads: 56
Joined: Jan 2018
Reputation:
307
Try subprocess.Popen([prg])
perhaps.
Posts: 567
Threads: 1
Joined: Aug 2019
Reputation:
55
May-04-2021, 08:28 AM
(This post was last modified: May-04-2021, 08:28 AM by ibreeden.)
(May-03-2021, 07:51 PM)herwin Wrote: In the new code
print(prg)will give:
Output:
C:\Program Files\Google\Chrome\Application\chrome.exeso the correct value is read into the variable.
No it is not correct. The path should be: «C:Program FilesGoogleChromeApplicationchrome.exe», so without the double backlashes.
The backslash has a special meaning in Python. So to assign a string literal with backslashes you have to double the backslash to make clear you really mean one backslash.
>>> prg = 'C:\Program Files\Google\Chrome\Application\chrome.exe' >>> print(prg) C:Program FilesGoogleChromeApplicationchrome.exe
So «prg» will contain only single backslashes.
Nowadays a more popular way to assign such a variable is to assign a raw string by putting an «r» before the string literal.
>>> prg = r'C:Program FilesGoogleChromeApplicationchrome.exe' >>> print(prg) C:Program FilesGoogleChromeApplicationchrome.exe
So make sure you get rid of the double backslashes.
Posts: 6,575
Threads: 116
Joined: Sep 2016
Reputation:
487
May-04-2021, 09:54 AM
(This post was last modified: May-04-2021, 09:55 AM by snippsat.)
(May-03-2021, 07:51 PM)herwin Wrote: gives the above-mentioned error code (if the file path has a black space it).
In the new code
print(prg)
Do print(repr(prg))
then you see if there is a space.
It’s normal when read from file eg csv to use strip()
so there no space at beginning or end.
>>> path = r'C:codefile.csv ' # Looks ok,but are not >>> print(path) C:codefile.csv >>> >>> # To see all >>> print(repr(path)) 'C:\code\file.csv ' >>> >>> # Fix >>> path.strip() 'C:\code\file.csv'
herwin
Programmer named Tim
Posts: 7
Threads: 1
Joined: May 2021
Reputation:
0
(May-03-2021, 09:15 PM)Gribouillis Wrote: Try
subprocess.Popen([prg])
perhaps.
Thank you for your answer.
Unfortunately the problem remains the same
herwin
Programmer named Tim
Posts: 7
Threads: 1
Joined: May 2021
Reputation:
0
(May-04-2021, 08:28 AM)ibreeden Wrote:
(May-03-2021, 07:51 PM)herwin Wrote: In the new code
print(prg)will give:
Output:
C:\Program Files\Google\Chrome\Application\chrome.exeso the correct value is read into the variable.
No it is not correct. The path should be: «C:Program FilesGoogleChromeApplicationchrome.exe», so without the double backlashes.
The backslash has a special meaning in Python. So to assign a string literal with backslashes you have to double the backslash to make clear you really mean one backslash.>>> prg = 'C:\Program Files\Google\Chrome\Application\chrome.exe' >>> print(prg) C:Program FilesGoogleChromeApplicationchrome.exeSo «prg» will contain only single backslashes.
Nowadays a more popular way to assign such a variable is to assign a raw string by putting an «r» before the string literal.>>> prg = r'C:Program FilesGoogleChromeApplicationchrome.exe' >>> print(prg) C:Program FilesGoogleChromeApplicationchrome.exeSo make sure you get rid of the double backslashes.
Thank you for your response and suggestions.
I have tried with the single and double backslashes in the csv file. The error message stays the same in both cases.
How do I read the values from the csv file into the prg variable as a raw string?
herwin
Programmer named Tim
Posts: 7
Threads: 1
Joined: May 2021
Reputation:
0
(May-04-2021, 09:54 AM)snippsat Wrote:
(May-03-2021, 07:51 PM)herwin Wrote: gives the above-mentioned error code (if the file path has a blank space it).
In the new code
print(prg)Do
print(repr(prg))
then you see if there is a space.
It’s normal when read from file eg csv to usestrip()
so there no space at beginning or end.>>> path = r'C:codefile.csv ' # Looks ok,but are not >>> print(path) C:codefile.csv >>> >>> # To see all >>> print(repr(path)) 'C:\code\file.csv ' >>> >>> # Fix >>> path.strip() 'C:\code\file.csv'
Thanks.
I check as per your suggestion and there are no spaces at the beginning or the end of the string.
The problem appears to be the blank space in the middle of the string (between ‘program’ and ‘files’ in the file path)
Posts: 3,889
Threads: 56
Joined: Jan 2018
Reputation:
307
Have you tried Popen([prg])
instead of Popen(prg)
? The less ambiguous way to call Popen() is to pass a list of the arguments.
herwin
Programmer named Tim
Posts: 7
Threads: 1
Joined: May 2021
Reputation:
0
(May-04-2021, 03:42 PM)Gribouillis Wrote: Have you tried
Popen([prg])
instead ofPopen(prg)
? The less ambiguous way to call Popen() is to pass a list of the arguments.
Thanks.
Yes, I did. Unfortunately that does not seem to solve the problem (I get the same error message)
Posts: 6,575
Threads: 116
Joined: Sep 2016
Reputation:
487
May-04-2021, 10:56 PM
(This post was last modified: May-04-2021, 10:56 PM by snippsat.)
(May-04-2021, 03:30 PM)herwin Wrote: The problem appears to be the blank space in the middle of the string (between ‘program’ and ‘files’ in the file path)
Should not be a problem,a quick test.
So this run fine no error,and open programs.
import subprocess core = r'C:Program FilesCore TempCore Temp.exe' prg = r'C:Program Files (x86)GoogleChromeApplicationchrome.exe' print(repr(core)) print(repr(prg)) subprocess.Popen([core]) subprocess.Popen([prg])
Output:
E:div_codenew
λ python p_open.py
'C:\Program Files\Core Temp\Core Temp.exe'
'C:\Program Files (x86)\Google\Chrome\Application\chrome.exe'
If put paths is a file,run fine.
Output:
# prog.csv
C:Program FilesCore TempCore Temp.exe,C:Program Files (x86)GoogleChromeApplicationchrome.exe
import subprocess import csv with open('prog.csv') as f: reader = csv.reader(f, delimiter=',') prog_lst = list(reader) for prog in prog_lst[0]: subprocess.Popen([prog])
so prog_lst
looks like this,se that there are two \
when read from a file,
then there is no need for r
(raw string) as if write/copy path yourself.
>>> prog_lst [['C:\Program Files\Core Temp\Core Temp.exe', 'C:\Program Files (x86)\Google\Chrome\Application\chrome.exe']]