1 | # Sample script to install Python and pip under Windows |
---|
2 | # Authors: Olivier Grisel, Jonathan Helmus, Kyle Kastner, and Alex Willmer |
---|
3 | # License: CC0 1.0 Universal: http://creativecommons.org/publicdomain/zero/1.0/ |
---|
4 | |
---|
5 | $MINICONDA_URL = "http://repo.continuum.io/miniconda/" |
---|
6 | $BASE_URL = "https://www.python.org/ftp/python/" |
---|
7 | $GET_PIP_URL = "https://bootstrap.pypa.io/get-pip.py" |
---|
8 | $GET_PIP_PATH = "C:\get-pip.py" |
---|
9 | |
---|
10 | $PYTHON_PRERELEASE_REGEX = @" |
---|
11 | (?x) |
---|
12 | (?<major>\d+) |
---|
13 | \. |
---|
14 | (?<minor>\d+) |
---|
15 | \. |
---|
16 | (?<micro>\d+) |
---|
17 | (?<prerelease>[a-z]{1,2}\d+) |
---|
18 | "@ |
---|
19 | |
---|
20 | |
---|
21 | function Download ($filename, $url) { |
---|
22 | $webclient = New-Object System.Net.WebClient |
---|
23 | |
---|
24 | $basedir = $pwd.Path + "\" |
---|
25 | $filepath = $basedir + $filename |
---|
26 | if (Test-Path $filename) { |
---|
27 | Write-Host "Reusing" $filepath |
---|
28 | return $filepath |
---|
29 | } |
---|
30 | |
---|
31 | # Download and retry up to 3 times in case of network transient errors. |
---|
32 | Write-Host "Downloading" $filename "from" $url |
---|
33 | $retry_attempts = 2 |
---|
34 | for ($i = 0; $i -lt $retry_attempts; $i++) { |
---|
35 | try { |
---|
36 | $webclient.DownloadFile($url, $filepath) |
---|
37 | break |
---|
38 | } |
---|
39 | Catch [Exception]{ |
---|
40 | Start-Sleep 1 |
---|
41 | } |
---|
42 | } |
---|
43 | if (Test-Path $filepath) { |
---|
44 | Write-Host "File saved at" $filepath |
---|
45 | } else { |
---|
46 | # Retry once to get the error message if any at the last try |
---|
47 | $webclient.DownloadFile($url, $filepath) |
---|
48 | } |
---|
49 | return $filepath |
---|
50 | } |
---|
51 | |
---|
52 | |
---|
53 | function ParsePythonVersion ($python_version) { |
---|
54 | if ($python_version -match $PYTHON_PRERELEASE_REGEX) { |
---|
55 | return ([int]$matches.major, [int]$matches.minor, [int]$matches.micro, |
---|
56 | $matches.prerelease) |
---|
57 | } |
---|
58 | $version_obj = [version]$python_version |
---|
59 | return ($version_obj.major, $version_obj.minor, $version_obj.build, "") |
---|
60 | } |
---|
61 | |
---|
62 | |
---|
63 | function DownloadPython ($python_version, $platform_suffix) { |
---|
64 | $major, $minor, $micro, $prerelease = ParsePythonVersion $python_version |
---|
65 | |
---|
66 | if (($major -le 2 -and $micro -eq 0) ` |
---|
67 | -or ($major -eq 3 -and $minor -le 2 -and $micro -eq 0) ` |
---|
68 | ) { |
---|
69 | $dir = "$major.$minor" |
---|
70 | $python_version = "$major.$minor$prerelease" |
---|
71 | } else { |
---|
72 | $dir = "$major.$minor.$micro" |
---|
73 | } |
---|
74 | |
---|
75 | if ($prerelease) { |
---|
76 | if (($major -le 2) ` |
---|
77 | -or ($major -eq 3 -and $minor -eq 1) ` |
---|
78 | -or ($major -eq 3 -and $minor -eq 2) ` |
---|
79 | -or ($major -eq 3 -and $minor -eq 3) ` |
---|
80 | ) { |
---|
81 | $dir = "$dir/prev" |
---|
82 | } |
---|
83 | } |
---|
84 | |
---|
85 | if (($major -le 2) -or ($major -le 3 -and $minor -le 4)) { |
---|
86 | $ext = "msi" |
---|
87 | if ($platform_suffix) { |
---|
88 | $platform_suffix = ".$platform_suffix" |
---|
89 | } |
---|
90 | } else { |
---|
91 | $ext = "exe" |
---|
92 | if ($platform_suffix) { |
---|
93 | $platform_suffix = "-$platform_suffix" |
---|
94 | } |
---|
95 | } |
---|
96 | |
---|
97 | $filename = "python-$python_version$platform_suffix.$ext" |
---|
98 | $url = "$BASE_URL$dir/$filename" |
---|
99 | $filepath = Download $filename $url |
---|
100 | return $filepath |
---|
101 | } |
---|
102 | |
---|
103 | |
---|
104 | function InstallPython ($python_version, $architecture, $python_home) { |
---|
105 | Write-Host "Installing Python" $python_version "for" $architecture "bit architecture to" $python_home |
---|
106 | if (Test-Path $python_home) { |
---|
107 | Write-Host $python_home "already exists, skipping." |
---|
108 | return $false |
---|
109 | } |
---|
110 | if ($architecture -eq "32") { |
---|
111 | $platform_suffix = "" |
---|
112 | } else { |
---|
113 | $platform_suffix = "amd64" |
---|
114 | } |
---|
115 | $installer_path = DownloadPython $python_version $platform_suffix |
---|
116 | $installer_ext = [System.IO.Path]::GetExtension($installer_path) |
---|
117 | Write-Host "Installing $installer_path to $python_home" |
---|
118 | $install_log = $python_home + ".log" |
---|
119 | if ($installer_ext -eq '.msi') { |
---|
120 | InstallPythonMSI $installer_path $python_home $install_log |
---|
121 | } else { |
---|
122 | InstallPythonEXE $installer_path $python_home $install_log |
---|
123 | } |
---|
124 | if (Test-Path $python_home) { |
---|
125 | Write-Host "Python $python_version ($architecture) installation complete" |
---|
126 | } else { |
---|
127 | Write-Host "Failed to install Python in $python_home" |
---|
128 | Get-Content -Path $install_log |
---|
129 | Exit 1 |
---|
130 | } |
---|
131 | } |
---|
132 | |
---|
133 | |
---|
134 | function InstallPythonEXE ($exepath, $python_home, $install_log) { |
---|
135 | $install_args = "/quiet InstallAllUsers=1 TargetDir=$python_home" |
---|
136 | RunCommand $exepath $install_args |
---|
137 | } |
---|
138 | |
---|
139 | |
---|
140 | function InstallPythonMSI ($msipath, $python_home, $install_log) { |
---|
141 | $install_args = "/qn /log $install_log /i $msipath TARGETDIR=$python_home" |
---|
142 | $uninstall_args = "/qn /x $msipath" |
---|
143 | RunCommand "msiexec.exe" $install_args |
---|
144 | if (-not(Test-Path $python_home)) { |
---|
145 | Write-Host "Python seems to be installed else-where, reinstalling." |
---|
146 | RunCommand "msiexec.exe" $uninstall_args |
---|
147 | RunCommand "msiexec.exe" $install_args |
---|
148 | } |
---|
149 | } |
---|
150 | |
---|
151 | function RunCommand ($command, $command_args) { |
---|
152 | Write-Host $command $command_args |
---|
153 | Start-Process -FilePath $command -ArgumentList $command_args -Wait -Passthru |
---|
154 | } |
---|
155 | |
---|
156 | |
---|
157 | function InstallPip ($python_home) { |
---|
158 | $pip_path = $python_home + "\Scripts\pip.exe" |
---|
159 | $python_path = $python_home + "\python.exe" |
---|
160 | if (-not(Test-Path $pip_path)) { |
---|
161 | Write-Host "Installing pip..." |
---|
162 | $webclient = New-Object System.Net.WebClient |
---|
163 | $webclient.DownloadFile($GET_PIP_URL, $GET_PIP_PATH) |
---|
164 | Write-Host "Executing:" $python_path $GET_PIP_PATH |
---|
165 | & $python_path $GET_PIP_PATH |
---|
166 | } else { |
---|
167 | Write-Host "pip already installed." |
---|
168 | } |
---|
169 | } |
---|
170 | |
---|
171 | |
---|
172 | function DownloadMiniconda ($python_version, $platform_suffix) { |
---|
173 | if ($python_version -eq "3.4") { |
---|
174 | $filename = "Miniconda3-3.5.5-Windows-" + $platform_suffix + ".exe" |
---|
175 | } else { |
---|
176 | $filename = "Miniconda-3.5.5-Windows-" + $platform_suffix + ".exe" |
---|
177 | } |
---|
178 | $url = $MINICONDA_URL + $filename |
---|
179 | $filepath = Download $filename $url |
---|
180 | return $filepath |
---|
181 | } |
---|
182 | |
---|
183 | |
---|
184 | function InstallMiniconda ($python_version, $architecture, $python_home) { |
---|
185 | Write-Host "Installing Python" $python_version "for" $architecture "bit architecture to" $python_home |
---|
186 | if (Test-Path $python_home) { |
---|
187 | Write-Host $python_home "already exists, skipping." |
---|
188 | return $false |
---|
189 | } |
---|
190 | if ($architecture -eq "32") { |
---|
191 | $platform_suffix = "x86" |
---|
192 | } else { |
---|
193 | $platform_suffix = "x86_64" |
---|
194 | } |
---|
195 | $filepath = DownloadMiniconda $python_version $platform_suffix |
---|
196 | Write-Host "Installing" $filepath "to" $python_home |
---|
197 | $install_log = $python_home + ".log" |
---|
198 | $args = "/S /D=$python_home" |
---|
199 | Write-Host $filepath $args |
---|
200 | Start-Process -FilePath $filepath -ArgumentList $args -Wait -Passthru |
---|
201 | if (Test-Path $python_home) { |
---|
202 | Write-Host "Python $python_version ($architecture) installation complete" |
---|
203 | } else { |
---|
204 | Write-Host "Failed to install Python in $python_home" |
---|
205 | Get-Content -Path $install_log |
---|
206 | Exit 1 |
---|
207 | } |
---|
208 | } |
---|
209 | |
---|
210 | |
---|
211 | function InstallMinicondaPip ($python_home) { |
---|
212 | $pip_path = $python_home + "\Scripts\pip.exe" |
---|
213 | $conda_path = $python_home + "\Scripts\conda.exe" |
---|
214 | if (-not(Test-Path $pip_path)) { |
---|
215 | Write-Host "Installing pip..." |
---|
216 | $args = "install --yes pip" |
---|
217 | Write-Host $conda_path $args |
---|
218 | Start-Process -FilePath "$conda_path" -ArgumentList $args -Wait -Passthru |
---|
219 | } else { |
---|
220 | Write-Host "pip already installed." |
---|
221 | } |
---|
222 | } |
---|
223 | |
---|
224 | function main () { |
---|
225 | InstallPython $env:PYTHON_VERSION $env:PYTHON_ARCH $env:PYTHON |
---|
226 | InstallPip $env:PYTHON |
---|
227 | } |
---|
228 | |
---|
229 | main |
---|