We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
Good old 'utf-8' codec error on Windows
Howdy,

I'm unable to run `tox -re linting` on pytest anymore. I'm getting this error:

```
λ tox -re linting
linting recreate: c:\pytest\.tox\linting
linting installdeps: pre-commit>=1.11.0
linting installed: aspy.yaml==1.2.0,cfgv==1.6.0,identify==1.4.2,importlib-metadata==0.9,nodeenv==1.3.3,pre-commit==1.16.0,pytest==3.6.0,PyYAML==5.1,six==1.12.0,toml==0.10.0,virtualenv==16.5.0,zipp==0.4.0
linting run-test-pre: PYTHONHASHSEED='335'
linting run-test: commands[0] | pre-commit run --all-files --show-diff-on-failure
An unexpected error has occurred: UnicodeDecodeError: 'utf-8' codec can't decode byte 0xe3 in position 282: invalid continuation byte
Check the log at C:\Users\Bruno/.cache\pre-commit\pre-commit.log
ERROR: InvocationError for command 'c:\pytest\.tox\linting\Scripts\pre-commit.EXE' run --all-files --show-diff-on-failure (exited with code 1)
```

Here's the contents of the log file:

```
An unexpected error has occurred: UnicodeDecodeError: 'utf-8' codec can't decode byte 0xe3 in position 282: invalid continuation byte
Traceback (most recent call last):
  File "c:\pytest\.tox\linting\lib\site-packages\pre_commit\error_handler.py", line 46, in error_handler
    yield
  File "c:\pytest\.tox\linting\lib\site-packages\pre_commit\main.py", line 294, in main
    return run(args.config, store, args)
  File "c:\pytest\.tox\linting\lib\site-packages\pre_commit\commands\run.py", line 285, in run
    install_hook_envs(hooks, store)
  File "c:\pytest\.tox\linting\lib\site-packages\pre_commit\repository.py", line 210, in install_hook_envs
    if not _need_installed():
  File "c:\pytest\.tox\linting\lib\site-packages\pre_commit\repository.py", line 205, in _need_installed
    if hook.install_key not in seen and not hook.installed():
  File "c:\pytest\.tox\linting\lib\site-packages\pre_commit\repository.py", line 75, in installed
    lang.healthy(self.prefix, self.language_version)
  File "c:\pytest\.tox\linting\lib\site-packages\pre_commit\languages\python.py", line 139, in healthy
    retcode, _, _ = cmd_output(
  File "c:\pytest\.tox\linting\lib\site-packages\pre_commit\util.py", line 149, in cmd_output
    stderr = stderr.decode(encoding)
UnicodeDecodeError: 'utf-8' codec can't decode byte 0xe3 in position 282: invalid continuation byte
```

I've seen #835, #330 and #245, so I've tried to cleanup the pre-commit cache and updating `pip` and `virtualenv`, both on my system and in the virtualenv I have for pytest:

```
(.env37) λ pip install -U virtualenv
Requirement already up-to-date: virtualenv in .\.env37\lib\site-packages (16.5.0)

(.env37) λ py -3.7 -m pip install -U virtualenv
Requirement already up-to-date: virtualenv in c:\users\bruno\appdata\local\programs\python\python37\lib\site-packages (16.5.0)

(.env37) λ .tox\linting\Scripts\pip install virtualenv -U
Requirement already up-to-date: virtualenv in .\.tox\linting\lib\site-packages (16.5.0)
```

Same for `pre-commit`:

```
(.env37) λ .tox\linting\Scripts\pip list
Package            Version
------------------ -------
aspy.yaml          1.2.0
cfgv               1.6.0
identify           1.4.2
importlib-metadata 0.9
nodeenv            1.3.3
pip                19.1.1
pre-commit         1.16.0
PyYAML             5.1
setuptools         41.0.1
six                1.12.0
toml               0.10.0
virtualenv         16.5.0
wheel              0.33.1
zipp               0.4.0

(.env37) λ pip list
Package            Version                Location
------------------ ---------------------- -------------
aspy.yaml          1.2.0
atomicwrites       1.3.0
attrs              19.1.0
cfgv               1.6.0
colorama           0.4.1
filelock           3.0.10
identify           1.4.2
importlib-metadata 0.9
more-itertools     7.0.0
nodeenv            1.3.3
pip                19.1.1
pluggy             0.9.0
pre-commit         1.16.0
py                 1.8.0
pytest             4.4.2.dev43+g8605ed2a1 c:\pytest\src
PyYAML             5.1
setuptools         39.0.1
six                1.12.0
toml               0.10.0
tox                3.9.0
virtualenv         16.5.0
zipp               0.4.0
```

Any hints @asottile? 🤔 

--- END ISSUE ---

Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
--- BEGIN FILES ---
Path: `pre_commit/languages/python.py`
Content:
```
1 from __future__ import unicode_literals
2 
3 import contextlib
4 import os
5 import sys
6 
7 import pre_commit.constants as C
8 from pre_commit.envcontext import envcontext
9 from pre_commit.envcontext import UNSET
10 from pre_commit.envcontext import Var
11 from pre_commit.languages import helpers
12 from pre_commit.parse_shebang import find_executable
13 from pre_commit.util import CalledProcessError
14 from pre_commit.util import clean_path_on_failure
15 from pre_commit.util import cmd_output
16 
17 
18 ENVIRONMENT_DIR = 'py_env'
19 
20 
21 def bin_dir(venv):
22     """On windows there's a different directory for the virtualenv"""
23     bin_part = 'Scripts' if os.name == 'nt' else 'bin'
24     return os.path.join(venv, bin_part)
25 
26 
27 def get_env_patch(venv):
28     return (
29         ('PYTHONHOME', UNSET),
30         ('VIRTUAL_ENV', venv),
31         ('PATH', (bin_dir(venv), os.pathsep, Var('PATH'))),
32     )
33 
34 
35 def _find_by_py_launcher(version):  # pragma: no cover (windows only)
36     if version.startswith('python'):
37         try:
38             return cmd_output(
39                 'py', '-{}'.format(version[len('python'):]),
40                 '-c', 'import sys; print(sys.executable)',
41             )[1].strip()
42         except CalledProcessError:
43             pass
44 
45 
46 def _get_default_version():  # pragma: no cover (platform dependent)
47     def _norm(path):
48         _, exe = os.path.split(path.lower())
49         exe, _, _ = exe.partition('.exe')
50         if find_executable(exe) and exe not in {'python', 'pythonw'}:
51             return exe
52 
53     # First attempt from `sys.executable` (or the realpath)
54     # On linux, I see these common sys.executables:
55     #
56     # system `python`: /usr/bin/python -> python2.7
57     # system `python2`: /usr/bin/python2 -> python2.7
58     # virtualenv v: v/bin/python (will not return from this loop)
59     # virtualenv v -ppython2: v/bin/python -> python2
60     # virtualenv v -ppython2.7: v/bin/python -> python2.7
61     # virtualenv v -ppypy: v/bin/python -> v/bin/pypy
62     for path in {sys.executable, os.path.realpath(sys.executable)}:
63         exe = _norm(path)
64         if exe:
65             return exe
66 
67     # Next try the `pythonX.X` executable
68     exe = 'python{}.{}'.format(*sys.version_info)
69     if find_executable(exe):
70         return exe
71 
72     if _find_by_py_launcher(exe):
73         return exe
74 
75     # Give a best-effort try for windows
76     if os.path.exists(r'C:\{}\python.exe'.format(exe.replace('.', ''))):
77         return exe
78 
79     # We tried!
80     return C.DEFAULT
81 
82 
83 def get_default_version():
84     # TODO: when dropping python2, use `functools.lru_cache(maxsize=1)`
85     try:
86         return get_default_version.cached_version
87     except AttributeError:
88         get_default_version.cached_version = _get_default_version()
89         return get_default_version()
90 
91 
92 def _sys_executable_matches(version):
93     if version == 'python':
94         return True
95     elif not version.startswith('python'):
96         return False
97 
98     try:
99         info = tuple(int(p) for p in version[len('python'):].split('.'))
100     except ValueError:
101         return False
102 
103     return sys.version_info[:len(info)] == info
104 
105 
106 def norm_version(version):
107     if os.name == 'nt':  # pragma: no cover (windows)
108         # first see if our current executable is appropriate
109         if _sys_executable_matches(version):
110             return sys.executable
111 
112         version_exec = _find_by_py_launcher(version)
113         if version_exec:
114             return version_exec
115 
116         # Try looking up by name
117         version_exec = find_executable(version)
118         if version_exec and version_exec != version:
119             return version_exec
120 
121         # If it is in the form pythonx.x search in the default
122         # place on windows
123         if version.startswith('python'):
124             return r'C:\{}\python.exe'.format(version.replace('.', ''))
125 
126     # Otherwise assume it is a path
127     return os.path.expanduser(version)
128 
129 
130 def py_interface(_dir, _make_venv):
131     @contextlib.contextmanager
132     def in_env(prefix, language_version):
133         envdir = prefix.path(helpers.environment_dir(_dir, language_version))
134         with envcontext(get_env_patch(envdir)):
135             yield
136 
137     def healthy(prefix, language_version):
138         with in_env(prefix, language_version):
139             retcode, _, _ = cmd_output(
140                 'python', '-c',
141                 'import ctypes, datetime, io, os, ssl, weakref',
142                 retcode=None,
143             )
144         return retcode == 0
145 
146     def run_hook(hook, file_args):
147         with in_env(hook.prefix, hook.language_version):
148             return helpers.run_xargs(hook, helpers.to_cmd(hook), file_args)
149 
150     def install_environment(prefix, version, additional_dependencies):
151         additional_dependencies = tuple(additional_dependencies)
152         directory = helpers.environment_dir(_dir, version)
153 
154         env_dir = prefix.path(directory)
155         with clean_path_on_failure(env_dir):
156             if version != C.DEFAULT:
157                 python = norm_version(version)
158             else:
159                 python = os.path.realpath(sys.executable)
160             _make_venv(env_dir, python)
161             with in_env(prefix, version):
162                 helpers.run_setup_cmd(
163                     prefix, ('pip', 'install', '.') + additional_dependencies,
164                 )
165 
166     return in_env, healthy, run_hook, install_environment
167 
168 
169 def make_venv(envdir, python):
170     env = dict(os.environ, VIRTUALENV_NO_DOWNLOAD='1')
171     cmd = (sys.executable, '-mvirtualenv', envdir, '-p', python)
172     cmd_output(*cmd, env=env, cwd='/')
173 
174 
175 _interface = py_interface(ENVIRONMENT_DIR, make_venv)
176 in_env, healthy, run_hook, install_environment = _interface
177
```
--- END FILES ---

Please first localize the bug based on the issue statement, and then generate a patch according to the `git diff` format fenced by three backticks.

Here is an example:

```diff
diff --git a/examples/server_async.py b/examples/server_async.py
--- a/examples/server_async.py
+++ b/examples/server_async.py
@@ -313,4 +313,4 @@
 
 
 if __name__ == "__main__":
-    asyncio.run(run_async_server("."), debug=True)
+    asyncio.run(run_async_server(), debug=True)
diff --git a/examples/server_sync.py b/examples/server_sync.py
--- a/examples/server_sync.py
+++ b/examples/server_sync.py
@@ -313,5 +313,5 @@
 
 
 if __name__ == "__main__":
-    server = run_sync_server(".")
+    server = run_sync_server()
     server.shutdown()

```

diff --git a/pre_commit/languages/python.py b/pre_commit/languages/python.py
--- a/pre_commit/languages/python.py
+++ b/pre_commit/languages/python.py
@@ -140,6 +140,7 @@
                 'python', '-c',
                 'import ctypes, datetime, io, os, ssl, weakref',
                 retcode=None,
+                encoding=None,
             )
         return retcode == 0

{"golden_diff": "diff --git a/pre_commit/languages/python.py b/pre_commit/languages/python.py\n--- a/pre_commit/languages/python.py\n+++ b/pre_commit/languages/python.py\n@@ -140,6 +140,7 @@\n                 'python', '-c',\n                 'import ctypes, datetime, io, os, ssl, weakref',\n                 retcode=None,\n+                encoding=None,\n             )\n         return retcode == 0\n", "issue": "Good old 'utf-8' codec error on Windows\nHowdy,\r\n\r\nI'm unable to run `tox -re linting` on pytest anymore. I'm getting this error:\r\n\r\n```\r\n\u03bb tox -re linting\r\nlinting recreate: c:\\pytest\\.tox\\linting\r\nlinting installdeps: pre-commit>=1.11.0\r\nlinting installed: aspy.yaml==1.2.0,cfgv==1.6.0,identify==1.4.2,importlib-metadata==0.9,nodeenv==1.3.3,pre-commit==1.16.0,pytest==3.6.0,PyYAML==5.1,six==1.12.0,toml==0.10.0,virtualenv==16.5.0,zipp==0.4.0\r\nlinting run-test-pre: PYTHONHASHSEED='335'\r\nlinting run-test: commands[0] | pre-commit run --all-files --show-diff-on-failure\r\nAn unexpected error has occurred: UnicodeDecodeError: 'utf-8' codec can't decode byte 0xe3 in position 282: invalid continuation byte\r\nCheck the log at C:\\Users\\Bruno/.cache\\pre-commit\\pre-commit.log\r\nERROR: InvocationError for command 'c:\\pytest\\.tox\\linting\\Scripts\\pre-commit.EXE' run --all-files --show-diff-on-failure (exited with code 1)\r\n```\r\n\r\nHere's the contents of the log file:\r\n\r\n```\r\nAn unexpected error has occurred: UnicodeDecodeError: 'utf-8' codec can't decode byte 0xe3 in position 282: invalid continuation byte\r\nTraceback (most recent call last):\r\n  File \"c:\\pytest\\.tox\\linting\\lib\\site-packages\\pre_commit\\error_handler.py\", line 46, in error_handler\r\n    yield\r\n  File \"c:\\pytest\\.tox\\linting\\lib\\site-packages\\pre_commit\\main.py\", line 294, in main\r\n    return run(args.config, store, args)\r\n  File \"c:\\pytest\\.tox\\linting\\lib\\site-packages\\pre_commit\\commands\\run.py\", line 285, in run\r\n    install_hook_envs(hooks, store)\r\n  File \"c:\\pytest\\.tox\\linting\\lib\\site-packages\\pre_commit\\repository.py\", line 210, in install_hook_envs\r\n    if not _need_installed():\r\n  File \"c:\\pytest\\.tox\\linting\\lib\\site-packages\\pre_commit\\repository.py\", line 205, in _need_installed\r\n    if hook.install_key not in seen and not hook.installed():\r\n  File \"c:\\pytest\\.tox\\linting\\lib\\site-packages\\pre_commit\\repository.py\", line 75, in installed\r\n    lang.healthy(self.prefix, self.language_version)\r\n  File \"c:\\pytest\\.tox\\linting\\lib\\site-packages\\pre_commit\\languages\\python.py\", line 139, in healthy\r\n    retcode, _, _ = cmd_output(\r\n  File \"c:\\pytest\\.tox\\linting\\lib\\site-packages\\pre_commit\\util.py\", line 149, in cmd_output\r\n    stderr = stderr.decode(encoding)\r\nUnicodeDecodeError: 'utf-8' codec can't decode byte 0xe3 in position 282: invalid continuation byte\r\n```\r\n\r\nI've seen #835, #330 and #245, so I've tried to cleanup the pre-commit cache and updating `pip` and `virtualenv`, both on my system and in the virtualenv I have for pytest:\r\n\r\n```\r\n(.env37) \u03bb pip install -U virtualenv\r\nRequirement already up-to-date: virtualenv in .\\.env37\\lib\\site-packages (16.5.0)\r\n\r\n(.env37) \u03bb py -3.7 -m pip install -U virtualenv\r\nRequirement already up-to-date: virtualenv in c:\\users\\bruno\\appdata\\local\\programs\\python\\python37\\lib\\site-packages (16.5.0)\r\n\r\n(.env37) \u03bb .tox\\linting\\Scripts\\pip install virtualenv -U\r\nRequirement already up-to-date: virtualenv in .\\.tox\\linting\\lib\\site-packages (16.5.0)\r\n```\r\n\r\nSame for `pre-commit`:\r\n\r\n```\r\n(.env37) \u03bb .tox\\linting\\Scripts\\pip list\r\nPackage            Version\r\n------------------ -------\r\naspy.yaml          1.2.0\r\ncfgv               1.6.0\r\nidentify           1.4.2\r\nimportlib-metadata 0.9\r\nnodeenv            1.3.3\r\npip                19.1.1\r\npre-commit         1.16.0\r\nPyYAML             5.1\r\nsetuptools         41.0.1\r\nsix                1.12.0\r\ntoml               0.10.0\r\nvirtualenv         16.5.0\r\nwheel              0.33.1\r\nzipp               0.4.0\r\n\r\n(.env37) \u03bb pip list\r\nPackage            Version                Location\r\n------------------ ---------------------- -------------\r\naspy.yaml          1.2.0\r\natomicwrites       1.3.0\r\nattrs              19.1.0\r\ncfgv               1.6.0\r\ncolorama           0.4.1\r\nfilelock           3.0.10\r\nidentify           1.4.2\r\nimportlib-metadata 0.9\r\nmore-itertools     7.0.0\r\nnodeenv            1.3.3\r\npip                19.1.1\r\npluggy             0.9.0\r\npre-commit         1.16.0\r\npy                 1.8.0\r\npytest             4.4.2.dev43+g8605ed2a1 c:\\pytest\\src\r\nPyYAML             5.1\r\nsetuptools         39.0.1\r\nsix                1.12.0\r\ntoml               0.10.0\r\ntox                3.9.0\r\nvirtualenv         16.5.0\r\nzipp               0.4.0\r\n```\r\n\r\nAny hints @asottile? \ud83e\udd14 \n", "before_files": [{"content": "from __future__ import unicode_literals\n\nimport contextlib\nimport os\nimport sys\n\nimport pre_commit.constants as C\nfrom pre_commit.envcontext import envcontext\nfrom pre_commit.envcontext import UNSET\nfrom pre_commit.envcontext import Var\nfrom pre_commit.languages import helpers\nfrom pre_commit.parse_shebang import find_executable\nfrom pre_commit.util import CalledProcessError\nfrom pre_commit.util import clean_path_on_failure\nfrom pre_commit.util import cmd_output\n\n\nENVIRONMENT_DIR = 'py_env'\n\n\ndef bin_dir(venv):\n    \"\"\"On windows there's a different directory for the virtualenv\"\"\"\n    bin_part = 'Scripts' if os.name == 'nt' else 'bin'\n    return os.path.join(venv, bin_part)\n\n\ndef get_env_patch(venv):\n    return (\n        ('PYTHONHOME', UNSET),\n        ('VIRTUAL_ENV', venv),\n        ('PATH', (bin_dir(venv), os.pathsep, Var('PATH'))),\n    )\n\n\ndef _find_by_py_launcher(version):  # pragma: no cover (windows only)\n    if version.startswith('python'):\n        try:\n            return cmd_output(\n                'py', '-{}'.format(version[len('python'):]),\n                '-c', 'import sys; print(sys.executable)',\n            )[1].strip()\n        except CalledProcessError:\n            pass\n\n\ndef _get_default_version():  # pragma: no cover (platform dependent)\n    def _norm(path):\n        _, exe = os.path.split(path.lower())\n        exe, _, _ = exe.partition('.exe')\n        if find_executable(exe) and exe not in {'python', 'pythonw'}:\n            return exe\n\n    # First attempt from `sys.executable` (or the realpath)\n    # On linux, I see these common sys.executables:\n    #\n    # system `python`: /usr/bin/python -> python2.7\n    # system `python2`: /usr/bin/python2 -> python2.7\n    # virtualenv v: v/bin/python (will not return from this loop)\n    # virtualenv v -ppython2: v/bin/python -> python2\n    # virtualenv v -ppython2.7: v/bin/python -> python2.7\n    # virtualenv v -ppypy: v/bin/python -> v/bin/pypy\n    for path in {sys.executable, os.path.realpath(sys.executable)}:\n        exe = _norm(path)\n        if exe:\n            return exe\n\n    # Next try the `pythonX.X` executable\n    exe = 'python{}.{}'.format(*sys.version_info)\n    if find_executable(exe):\n        return exe\n\n    if _find_by_py_launcher(exe):\n        return exe\n\n    # Give a best-effort try for windows\n    if os.path.exists(r'C:\\{}\\python.exe'.format(exe.replace('.', ''))):\n        return exe\n\n    # We tried!\n    return C.DEFAULT\n\n\ndef get_default_version():\n    # TODO: when dropping python2, use `functools.lru_cache(maxsize=1)`\n    try:\n        return get_default_version.cached_version\n    except AttributeError:\n        get_default_version.cached_version = _get_default_version()\n        return get_default_version()\n\n\ndef _sys_executable_matches(version):\n    if version == 'python':\n        return True\n    elif not version.startswith('python'):\n        return False\n\n    try:\n        info = tuple(int(p) for p in version[len('python'):].split('.'))\n    except ValueError:\n        return False\n\n    return sys.version_info[:len(info)] == info\n\n\ndef norm_version(version):\n    if os.name == 'nt':  # pragma: no cover (windows)\n        # first see if our current executable is appropriate\n        if _sys_executable_matches(version):\n            return sys.executable\n\n        version_exec = _find_by_py_launcher(version)\n        if version_exec:\n            return version_exec\n\n        # Try looking up by name\n        version_exec = find_executable(version)\n        if version_exec and version_exec != version:\n            return version_exec\n\n        # If it is in the form pythonx.x search in the default\n        # place on windows\n        if version.startswith('python'):\n            return r'C:\\{}\\python.exe'.format(version.replace('.', ''))\n\n    # Otherwise assume it is a path\n    return os.path.expanduser(version)\n\n\ndef py_interface(_dir, _make_venv):\n    @contextlib.contextmanager\n    def in_env(prefix, language_version):\n        envdir = prefix.path(helpers.environment_dir(_dir, language_version))\n        with envcontext(get_env_patch(envdir)):\n            yield\n\n    def healthy(prefix, language_version):\n        with in_env(prefix, language_version):\n            retcode, _, _ = cmd_output(\n                'python', '-c',\n                'import ctypes, datetime, io, os, ssl, weakref',\n                retcode=None,\n            )\n        return retcode == 0\n\n    def run_hook(hook, file_args):\n        with in_env(hook.prefix, hook.language_version):\n            return helpers.run_xargs(hook, helpers.to_cmd(hook), file_args)\n\n    def install_environment(prefix, version, additional_dependencies):\n        additional_dependencies = tuple(additional_dependencies)\n        directory = helpers.environment_dir(_dir, version)\n\n        env_dir = prefix.path(directory)\n        with clean_path_on_failure(env_dir):\n            if version != C.DEFAULT:\n                python = norm_version(version)\n            else:\n                python = os.path.realpath(sys.executable)\n            _make_venv(env_dir, python)\n            with in_env(prefix, version):\n                helpers.run_setup_cmd(\n                    prefix, ('pip', 'install', '.') + additional_dependencies,\n                )\n\n    return in_env, healthy, run_hook, install_environment\n\n\ndef make_venv(envdir, python):\n    env = dict(os.environ, VIRTUALENV_NO_DOWNLOAD='1')\n    cmd = (sys.executable, '-mvirtualenv', envdir, '-p', python)\n    cmd_output(*cmd, env=env, cwd='/')\n\n\n_interface = py_interface(ENVIRONMENT_DIR, make_venv)\nin_env, healthy, run_hook, install_environment = _interface\n", "path": "pre_commit/languages/python.py"}], "after_files": [{"content": "from __future__ import unicode_literals\n\nimport contextlib\nimport os\nimport sys\n\nimport pre_commit.constants as C\nfrom pre_commit.envcontext import envcontext\nfrom pre_commit.envcontext import UNSET\nfrom pre_commit.envcontext import Var\nfrom pre_commit.languages import helpers\nfrom pre_commit.parse_shebang import find_executable\nfrom pre_commit.util import CalledProcessError\nfrom pre_commit.util import clean_path_on_failure\nfrom pre_commit.util import cmd_output\n\n\nENVIRONMENT_DIR = 'py_env'\n\n\ndef bin_dir(venv):\n    \"\"\"On windows there's a different directory for the virtualenv\"\"\"\n    bin_part = 'Scripts' if os.name == 'nt' else 'bin'\n    return os.path.join(venv, bin_part)\n\n\ndef get_env_patch(venv):\n    return (\n        ('PYTHONHOME', UNSET),\n        ('VIRTUAL_ENV', venv),\n        ('PATH', (bin_dir(venv), os.pathsep, Var('PATH'))),\n    )\n\n\ndef _find_by_py_launcher(version):  # pragma: no cover (windows only)\n    if version.startswith('python'):\n        try:\n            return cmd_output(\n                'py', '-{}'.format(version[len('python'):]),\n                '-c', 'import sys; print(sys.executable)',\n            )[1].strip()\n        except CalledProcessError:\n            pass\n\n\ndef _get_default_version():  # pragma: no cover (platform dependent)\n    def _norm(path):\n        _, exe = os.path.split(path.lower())\n        exe, _, _ = exe.partition('.exe')\n        if find_executable(exe) and exe not in {'python', 'pythonw'}:\n            return exe\n\n    # First attempt from `sys.executable` (or the realpath)\n    # On linux, I see these common sys.executables:\n    #\n    # system `python`: /usr/bin/python -> python2.7\n    # system `python2`: /usr/bin/python2 -> python2.7\n    # virtualenv v: v/bin/python (will not return from this loop)\n    # virtualenv v -ppython2: v/bin/python -> python2\n    # virtualenv v -ppython2.7: v/bin/python -> python2.7\n    # virtualenv v -ppypy: v/bin/python -> v/bin/pypy\n    for path in {sys.executable, os.path.realpath(sys.executable)}:\n        exe = _norm(path)\n        if exe:\n            return exe\n\n    # Next try the `pythonX.X` executable\n    exe = 'python{}.{}'.format(*sys.version_info)\n    if find_executable(exe):\n        return exe\n\n    if _find_by_py_launcher(exe):\n        return exe\n\n    # Give a best-effort try for windows\n    if os.path.exists(r'C:\\{}\\python.exe'.format(exe.replace('.', ''))):\n        return exe\n\n    # We tried!\n    return C.DEFAULT\n\n\ndef get_default_version():\n    # TODO: when dropping python2, use `functools.lru_cache(maxsize=1)`\n    try:\n        return get_default_version.cached_version\n    except AttributeError:\n        get_default_version.cached_version = _get_default_version()\n        return get_default_version()\n\n\ndef _sys_executable_matches(version):\n    if version == 'python':\n        return True\n    elif not version.startswith('python'):\n        return False\n\n    try:\n        info = tuple(int(p) for p in version[len('python'):].split('.'))\n    except ValueError:\n        return False\n\n    return sys.version_info[:len(info)] == info\n\n\ndef norm_version(version):\n    if os.name == 'nt':  # pragma: no cover (windows)\n        # first see if our current executable is appropriate\n        if _sys_executable_matches(version):\n            return sys.executable\n\n        version_exec = _find_by_py_launcher(version)\n        if version_exec:\n            return version_exec\n\n        # Try looking up by name\n        version_exec = find_executable(version)\n        if version_exec and version_exec != version:\n            return version_exec\n\n        # If it is in the form pythonx.x search in the default\n        # place on windows\n        if version.startswith('python'):\n            return r'C:\\{}\\python.exe'.format(version.replace('.', ''))\n\n    # Otherwise assume it is a path\n    return os.path.expanduser(version)\n\n\ndef py_interface(_dir, _make_venv):\n    @contextlib.contextmanager\n    def in_env(prefix, language_version):\n        envdir = prefix.path(helpers.environment_dir(_dir, language_version))\n        with envcontext(get_env_patch(envdir)):\n            yield\n\n    def healthy(prefix, language_version):\n        with in_env(prefix, language_version):\n            retcode, _, _ = cmd_output(\n                'python', '-c',\n                'import ctypes, datetime, io, os, ssl, weakref',\n                retcode=None,\n                encoding=None,\n            )\n        return retcode == 0\n\n    def run_hook(hook, file_args):\n        with in_env(hook.prefix, hook.language_version):\n            return helpers.run_xargs(hook, helpers.to_cmd(hook), file_args)\n\n    def install_environment(prefix, version, additional_dependencies):\n        additional_dependencies = tuple(additional_dependencies)\n        directory = helpers.environment_dir(_dir, version)\n\n        env_dir = prefix.path(directory)\n        with clean_path_on_failure(env_dir):\n            if version != C.DEFAULT:\n                python = norm_version(version)\n            else:\n                python = os.path.realpath(sys.executable)\n            _make_venv(env_dir, python)\n            with in_env(prefix, version):\n                helpers.run_setup_cmd(\n                    prefix, ('pip', 'install', '.') + additional_dependencies,\n                )\n\n    return in_env, healthy, run_hook, install_environment\n\n\ndef make_venv(envdir, python):\n    env = dict(os.environ, VIRTUALENV_NO_DOWNLOAD='1')\n    cmd = (sys.executable, '-mvirtualenv', envdir, '-p', python)\n    cmd_output(*cmd, env=env, cwd='/')\n\n\n_interface = py_interface(ENVIRONMENT_DIR, make_venv)\nin_env, healthy, run_hook, install_environment = _interface\n", "path": "pre_commit/languages/python.py"}]}