You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
subprocess: support bytes program name (POSIX) #52759
Note: these values reflect the state of the issue at the time it was migrated and might not reflect the current state.
Show more details
GitHub fields:
assignee=Noneclosed_at=<Date2010-05-18.17:25:07.128>created_at=<Date2010-04-23.22:42:05.444>labels= ['library', 'expert-unicode']
title='subprocess: support bytes program name (POSIX)'updated_at=<Date2011-03-03.12:55:08.983>user='https://github.com/vstinner'
While fixing bpo-8391, I realized that subprocess doesn't support bytes program name if it's not an absolute path:
-------
$ ./python
>>> import subprocess
>>> subprocess.call([b'echo'])
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "/home/SHARE/SVN/py3k/Lib/subprocess.py", line 449, in call
return Popen(*popenargs, **kwargs).wait()
File "/home/SHARE/SVN/py3k/Lib/subprocess.py", line 681, in __init__
restore_signals, start_new_session)
File "/home/SHARE/SVN/py3k/Lib/subprocess.py", line 1116, in _execute_child
for exe in executable_list)
File "/home/SHARE/SVN/py3k/Lib/subprocess.py", line 1115, in <genexpr>
executable_list = tuple(fs_encode(exe)
File "/home/SHARE/SVN/py3k/Lib/subprocess.py", line 1114, in <genexpr>
for dir in path_list)
File "/home/SHARE/SVN/py3k/Lib/posixpath.py", line 75, in join
if b.startswith(sep):
TypeError: expected an object with the buffer interface
[62826 refs]
I proposed the creation of fs_encode() and fs_decode() functions in os.path: see bpo-8514. There functions would simplify my patch, but also make it correct on all OS (Windows, Mac, Linux).
Bytes program name problem should be splitted in two parts:
(a) subprocess.call([b'env']) and subprocess.call([b'env'], env={'PATH': '/usr/bin'}): bytes program and unicode environ
(b) bytes program and bytes environ
Part (a)
--------
(a) would benefit from the creation of os(.path).fsencode() function (issue bpo-8514).
Part (b)
--------
If the creation of os.environb is accepted (bpo-8603), I think that subprocess should also be modified to support pure bytes environ. Mix bytes and unicode variables in env would lead to mojibake and headaches.
So I propose the creation of an "envb" (environment bytes) argument to Popen constructor. (b) would be written as:
(and it will not be possible to define env and envb at the same time)
In this case, we will need a pure bytes version of os.get_exec_path(), and os._execvpe() should have a "bytes environment" mode (add an optional argument).
--
I have a patch fixing both problems, parts (a) and (b), but the patch depends on os.environb. I prefer to wait until os.environb is accepted to submit my patch.
It would benefit from fsencode/fsdecode functions rather
than manually doing the 'surrogateescape' thing everywhere.
I choosed to drop the idea of fsdecode() (patch for part A doesn't decode bytes anymore, it only encodes str). bpo-8514 has now a short and simple patch. I'm waiting for the final decision on bpo-8514 to commit the part A.
Also, could you add a unittest for os._execvpe to test its behavior?
os._execvpe() is a protected function. issue8513_partA.patch includes a test for subprocess. test_subprocess in two twices: with _posixsubprocess (C module) and with the pure Python implementation. The pure Python implementation calls os._execvpe(), that's why I patched also this function in my patch ;-)
I asked on #python-dev about os.get_exec_path() result type. As expected, the answer was "It's a really bad idea".
So here is a new version of my patch. Summary of the patch version 4:
subprocess.Popen() and os._execvpe() support bytes program name
os.get_exec_path() now supports b'PATH' key and bytes value
add os.supports_bytes_environ flag: "True if the native OS type of the environment is bytes (eg. False on Windows)"
Changes since the version 3:
document the new os.supports_bytes_environ flag
os.get_exec_path() result type is always str (decode bytes to str using sys.getfilesystemencoding() + surrogateescape)
path.supports_unicode_filenames is False on Windows 9x but Windows 9x native type is unicode and so fsencode() should not be defined on this OS: revert the fsencode() test (if not path.supports_unicode_filenames => if name != 'nt')
Ok, everything is ready for this issue: os.environb and os.fsencode() are commited, and test_os is prepared to test os._execvpe() change. I'm just waiting for a review.
Execpt the change on os.get_exec_path(), the patch is now simple.
Activity
vstinner commentedon Apr 23, 2010
While fixing bpo-8391, I realized that subprocess doesn't support bytes program name if it's not an absolute path:
-------
I'm working on a patch.
vstinner commentedon Apr 23, 2010
Attached patch (draft version) fixes this issue.
vstinner commentedon Apr 23, 2010
I proposed the creation of fs_encode() and fs_decode() functions in os.path: see bpo-8514. There functions would simplify my patch, but also make it correct on all OS (Windows, Mac, Linux).
vstinner commentedon Apr 26, 2010
My patch changes:
[-]subprocess: support bytes program name[/-][+]subprocess: support bytes program name (POSIX)[/+]vstinner commentedon May 4, 2010
Bytes program name problem should be splitted in two parts:
(a) subprocess.call([b'env']) and subprocess.call([b'env'], env={'PATH': '/usr/bin'}): bytes program and unicode environ
(b) bytes program and bytes environ
Part (a)
--------
(a) would benefit from the creation of os(.path).fsencode() function (issue bpo-8514).
Part (b)
--------
If the creation of os.environb is accepted (bpo-8603), I think that subprocess should also be modified to support pure bytes environ. Mix bytes and unicode variables in env would lead to mojibake and headaches.
So I propose the creation of an "envb" (environment bytes) argument to Popen constructor. (b) would be written as:
or
(and it will not be possible to define env and envb at the same time)
In this case, we will need a pure bytes version of os.get_exec_path(), and os._execvpe() should have a "bytes environment" mode (add an optional argument).
--
I have a patch fixing both problems, parts (a) and (b), but the patch depends on os.environb. I prefer to wait until os.environb is accepted to submit my patch.
vstinner commentedon May 6, 2010
New patch (issue8513_partA.patch):
vstinner commentedon May 6, 2010
I fixed bpo-8603 and opened bpo-8640 for subprocess and envb.
gpshead commentedon May 8, 2010
I think your partA patch makes sense.
It would benefit from fsencode/fsdecode functions rather than manually doing the 'surrogateescape' thing everywhere.
Also, could you add a unittest for os._execvpe to test its behavior?
vstinner commentedon May 8, 2010
I can fix part A and B in two commits.
I choosed to drop the idea of fsdecode() (patch for part A doesn't decode bytes anymore, it only encodes str). bpo-8514 has now a short and simple patch. I'm waiting for the final decision on bpo-8514 to commit the part A.
os._execvpe() is a protected function. issue8513_partA.patch includes a test for subprocess. test_subprocess in two twices: with _posixsubprocess (C module) and with the pure Python implementation. The pure Python implementation calls os._execvpe(), that's why I patched also this function in my patch ;-)
vstinner commentedon May 8, 2010
Update the patch to use os.fsencode().
gpshead commentedon May 8, 2010
Build on the os._execvpe unittest I added in py3k r81001. Protected functions are perfectly fine things to unittest.
vstinner commentedon May 9, 2010
The test fails on Windows.
======================================================================
FAIL: test_internal_execvpe (test.test_os.ExecTests)
----------------------------------------------------------------------
First differing element 0:
('execve', '/p/f', (['-a'], {'spam': 'beans'}))
('execve', '/p\\f', (['-a'], {'spam': 'beans'}))
? ^
+ [('execve', '/p\\f', (['-a'], {'spam': 'beans'})),
? ^^
? ^
+ ('execve', '/pp\\f', (['-a'], {'spam': 'beans'}))]
? ^^
gpshead commentedon May 9, 2010
my bad. hopefully r81019 fixes that.
vstinner commentedon May 16, 2010
New patch fixing this issue:
I'm not proud of the change on os.get_exec_path() result type, I'm not sure that it's the right thing to do. But at least, the patch works :-)
vstinner commentedon May 16, 2010
Oops, I forgot to add the new patch: subprocess_bytes_program-3.patch.
vstinner commentedon May 16, 2010
I asked on #python-dev about os.get_exec_path() result type. As expected, the answer was "It's a really bad idea".
So here is a new version of my patch. Summary of the patch version 4:
Changes since the version 3:
vstinner commentedon May 17, 2010
I forgot to update test_os: patch version 5.
vstinner commentedon May 17, 2010
Ok, everything is ready for this issue: os.environb and os.fsencode() are commited, and test_os is prepared to test os._execvpe() change. I'm just waiting for a review.
Execpt the change on os.get_exec_path(), the patch is now simple.
vstinner commentedon May 18, 2010
Hum, os.get_exec_path() has no test for the new features (support b'PATH' key and bytes value).
vstinner commentedon May 18, 2010
Fixed by r81291 + r81292 (py3k).
The final commit contains much more tests ;-) I will watch the buildbot next hours and block the commit in 3.1.
vstinner commentedon Mar 3, 2011
Oh, I forget subprocess.call(b'ls'): command as a byte string => fixed in Python 3.3 (r88720).