54 | def find_python_executable(python_major): |
55 | |
56 | """ |
57 | Find the relevant python executable that is of the given python major version. |
58 | Will test, in decreasing priority order: |
59 | * the current Python interpreter |
60 | * 'pythonX' executable in PATH (with X the given major version) if available |
61 | * 'python' executable in PATH if available |
62 | * Windows Python launcher 'py' executable in PATH if available |
63 | Incompatible python versions for Certbot will be evicted (eg. Python < 3.5 on Windows) |
64 | :param int python_major: the Python major version to target (2 or 3) |
65 | :rtype: str |
66 | :return: the relevant python executable path |
67 | :raise RuntimeError: if no relevant python executable path could be found |
68 | """ |
69 | python_executable_path = None |
70 | |
71 | |
72 | if _check_version('{0}.{1}.{2}'.format( |
73 | sys.version_info[0], sys.version_info[1], sys.version_info[2]), python_major): |
74 | return sys.executable |
75 | |
76 | |
77 | versions_to_test = ['2.7', '2', ''] if python_major == 2 else ['3', ''] |
78 | for one_version in versions_to_test: |
79 | try: |
80 | one_python = 'python{0}'.format(one_version) |
81 | output = subprocess.check_output([one_python, '--version'], |
82 | universal_newlines=True, stderr=subprocess.STDOUT) |
83 | if _check_version(output.strip().split()[1], python_major): |
84 | return subprocess.check_output([one_python, '-c', |
85 | 'import sys; sys.stdout.write(sys.executable);'], |
86 | universal_newlines=True) |
87 | except (subprocess.CalledProcessError, OSError): |
88 | pass |
89 | |
90 | |
91 | try: |
92 | env_arg = '-{0}'.format(python_major) |
93 | output_version = subprocess.check_output(['py', env_arg, '--version'], |
94 | universal_newlines=True, stderr=subprocess.STDOUT) |
95 | if _check_version(output_version.strip().split()[1], python_major): |
96 | return subprocess.check_output(['py', env_arg, '-c', |
97 | 'import sys; sys.stdout.write(sys.executable);'], |
98 | universal_newlines=True) |
99 | except (subprocess.CalledProcessError, OSError): |
100 | pass |
101 | |
102 | if not python_executable_path: |
103 | raise RuntimeError('Error, no compatible Python {0} executable for Certbot could be found.' |
104 | .format(python_major)) |