Issue #18283: shutil.which() now supports bytes argument, not only text argument.
diff --git a/Lib/shutil.py b/Lib/shutil.py
index 502bb67..c80a5cc 100644
--- a/Lib/shutil.py
+++ b/Lib/shutil.py
@@ -1065,6 +1065,13 @@
 
     return os.terminal_size((columns, lines))
 
+# Check that a given file can be accessed with the correct mode.
+# Additionally check that `file` is not a directory, as on Windows
+# directories pass the os.access check.
+def _access_check(fn, mode):
+    return (os.path.exists(fn) and os.access(fn, mode)
+            and not os.path.isdir(fn))
+
 def which(cmd, mode=os.F_OK | os.X_OK, path=None):
     """Given a command, mode, and a PATH string, return the path which
     conforms to the given mode on the PATH, or None if there is no such
@@ -1075,13 +1082,6 @@
     path.
 
     """
-    # Check that a given file can be accessed with the correct mode.
-    # Additionally check that `file` is not a directory, as on Windows
-    # directories pass the os.access check.
-    def _access_check(fn, mode):
-        return (os.path.exists(fn) and os.access(fn, mode)
-                and not os.path.isdir(fn))
-
     # If we're given a path with a directory part, look it up directly rather
     # than referring to PATH directories. This includes checking relative to the
     # current directory, e.g. ./script
@@ -1094,7 +1094,12 @@
         path = os.environ.get("PATH", os.defpath)
     if not path:
         return None
-    path = path.split(os.pathsep)
+    if isinstance(cmd, bytes):
+        path = os.fsencode(path)
+        path = path.split(os.fsencode(os.pathsep))
+    else:
+        path = os.fsdecode(path)
+        path = path.split(os.pathsep)
 
     if sys.platform == "win32":
         # The current directory takes precedence on Windows.
@@ -1103,6 +1108,8 @@
 
         # PATHEXT is necessary to check on Windows.
         pathext = os.environ.get("PATHEXT", "").split(os.pathsep)
+        if isinstance(cmd, bytes):
+            pathext = map(os.fsencode, pathext)
         # See if the given file matches any of the expected path extensions.
         # This will allow us to short circuit when given "python.exe".
         # If it does match, only test that one, otherwise we have to try