Index: Lib/test/test_subprocess.py =================================================================== --- Lib/test/test_subprocess.py (révision 81227) +++ Lib/test/test_subprocess.py (copie de travail) @@ -825,7 +825,14 @@ stdout = stdout.rstrip(b'\n\r') self.assertEquals(stdout.decode('ascii'), repr(value)) + def test_canonicalize_env(self): + env = os.environ.copy() + env['TEST'] = '1' + env[b'TEST'] = b'2' + self.assertRaises(ValueError, + subprocess.call, [sys.executable], env=env) + @unittest.skipUnless(mswindows, "Windows specific tests") class Win32ProcessTestCase(BaseTestCase): Index: Lib/subprocess.py =================================================================== --- Lib/subprocess.py (révision 81227) +++ Lib/subprocess.py (copie de travail) @@ -1077,6 +1077,17 @@ if executable is None: executable = args[0] + if env is not None: + envb = dict() + for key, value in env.items(): + key = os.fsencode(key) + if key in envb: + raise ValueError( + "env contains two variables with the same " + "name ({!r}) but different types".format(key)) + envb[key] = os.fsencode(value) + env = envb + # For transferring possible exec failure from child to parent. # Data format: "exception name:hex errno:description" # Pickle is not used; it is complex and involves memory allocation. @@ -1092,8 +1103,7 @@ # and pass it to fork_exec() if env: - env_list = [os.fsencode(k) + b'=' + os.fsencode(v) - for k, v in env.items()] + env_list = [(k + b'=' + v) for k, v in env.items()] else: env_list = None # Use execv instead of execve. if os.path.dirname(executable):