11# Sample script to install Python and pip under Windows
2- # Authors: Olivier Grisel and Kyle Kastner
3- # License: BSD 3 clause
2+ # Authors: Olivier Grisel, Jonathan Helmus, Kyle Kastner, and Alex Willmer
3+ # License: CC0 1.0 Universal: http://creativecommons.org/publicdomain/zero/1.0/
44
5+ $MINICONDA_URL = " http://repo.continuum.io/miniconda/"
56$BASE_URL = " https://www.python.org/ftp/python/"
67$GET_PIP_URL = " https://bootstrap.pypa.io/get-pip.py"
78$GET_PIP_PATH = " C:\get-pip.py"
89
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+ "@
919
10- function DownloadPython ($python_version , $platform_suffix ) {
20+
21+ function Download ($filename , $url ) {
1122 $webclient = New-Object System.Net.WebClient
12- $filename = " python-" + $python_version + $platform_suffix + " .msi"
13- $url = $BASE_URL + $python_version + " /" + $filename
1423
1524 $basedir = $pwd.Path + " \"
1625 $filepath = $basedir + $filename
@@ -22,22 +31,73 @@ function DownloadPython ($python_version, $platform_suffix) {
2231 # Download and retry up to 3 times in case of network transient errors.
2332 Write-Host " Downloading" $filename " from" $url
2433 $retry_attempts = 2
25- for ($i = 0 ; $i -lt $retry_attempts ; $i ++ ){
34+ for ($i = 0 ; $i -lt $retry_attempts ; $i ++ ) {
2635 try {
2736 $webclient.DownloadFile ($url , $filepath )
2837 break
2938 }
3039 Catch [Exception ]{
3140 Start-Sleep 1
3241 }
33- }
34- if (Test-Path $filepath ) {
35- Write-Host " File saved at" $filepath
36- } else {
37- # Retry once to get the error message if any at the last try
38- $webclient.DownloadFile ($url , $filepath )
39- }
40- return $filepath
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
41101}
42102
43103
@@ -50,18 +110,16 @@ function InstallPython ($python_version, $architecture, $python_home) {
50110 if ($architecture -eq " 32" ) {
51111 $platform_suffix = " "
52112 } else {
53- $platform_suffix = " . amd64"
113+ $platform_suffix = " amd64"
54114 }
55- $msipath = DownloadPython $python_version $platform_suffix
56- Write-Host " Installing" $msipath " to" $python_home
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 "
57118 $install_log = $python_home + " .log"
58- $install_args = " /qn /log $install_log /i $msipath TARGETDIR=$python_home "
59- $uninstall_args = " /qn /x $msipath "
60- RunCommand " msiexec.exe" $install_args
61- if (-not (Test-Path $python_home )) {
62- Write-Host " Python seems to be installed else-where, reinstalling."
63- RunCommand " msiexec.exe" $uninstall_args
64- RunCommand " msiexec.exe" $install_args
119+ if ($installer_ext -eq ' .msi' ) {
120+ InstallPythonMSI $installer_path $python_home $install_log
121+ } else {
122+ InstallPythonEXE $installer_path $python_home $install_log
65123 }
66124 if (Test-Path $python_home ) {
67125 Write-Host " Python $python_version ($architecture ) installation complete"
@@ -72,6 +130,24 @@ function InstallPython ($python_version, $architecture, $python_home) {
72130 }
73131}
74132
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+
75151function RunCommand ($command , $command_args ) {
76152 Write-Host $command $command_args
77153 Start-Process - FilePath $command - ArgumentList $command_args - Wait - Passthru
@@ -86,13 +162,65 @@ function InstallPip ($python_home) {
86162 $webclient = New-Object System.Net.WebClient
87163 $webclient.DownloadFile ($GET_PIP_URL , $GET_PIP_PATH )
88164 Write-Host " Executing:" $python_path $GET_PIP_PATH
89- Start-Process - FilePath " $python_path " - ArgumentList " $GET_PIP_PATH " - Wait - Passthru
165+ & $python_path $GET_PIP_PATH
90166 } else {
91167 Write-Host " pip already installed."
92168 }
93169}
94170
95171
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+
96224function main () {
97225 InstallPython $env: PYTHON_VERSION $env: PYTHON_ARCH $env: PYTHON
98226 InstallPip $env: PYTHON
0 commit comments