Developing on windows¶
This is a sketch of the steps that I (MB) went through setting up a semi-standard development environment for python packaging on windows.
My system(s)¶
I’ve got several Windows 7 instances running mainly as buildbot machines, a Windows 8 machine kindly donated by Chris Holdgraf of the UC Berkeley Knight lab, and some virtual machines, also running Windows 7. I used to have some XP machines, but UC Berkeley doesn’t allow them on the network any more.
Basic setup¶
Shell: in the old days, we had to use the awful Windows
cmd
shell. It’s still useful sometimes, but the newer powershell is vastly better. It comes installed with Windows 7 and later. If you are using Vista or XP (really?), you will have to install it (see links from powershell page). Compared tocmd
, Powershell has better command and filename completion,ls
for directory listing, a less idiosyncraticcd
, and a less painful scripting language. I believe I’ve used version 1 and version 2.$Host.version
at the powershell prompt gave me1 0 0 0
on my old XP installation. Don’t forget to enable quickedit mode for much nicer right-click copy and paste.Install msysgit. In the installation, set
git
to be on the command path, but not the git bash utilities. I set the repo to have LF endings, but the checked out files to have system endings. You’ll see this setting offered in the installation GUI - it setscore.autocrlf=input
in your global git config.
SSH setup¶
msysgit has ssh, but for various reasons I wanted to be able to use powershell with git. In order to do this I need to get git SSH authentication working via the windows tools:
Install putty. Well, in fact, install all the putty utilities via the windows installer - including plink and pageant. These are utilities we need for handling ssh authentication for git and other tools.
You might consider putting the Putty directory on the path. Something like:
$my_path = [Environment]::GetEnvironmentVariable("PATH","User") $my_path += ";C:\Program files (x86)\Putty" # (x86) on my windows 7 system [Environment]::SetEnvironmentVariable("PATH", $my_path, "User")
I have ssh keys I use on unix and mac. I got the necessary ssh keys via sftp (installed by Putty installer). These went into
$HOME/.ssh
. I then ran PUTTYgen (installed by the Putty installer) to import the Unix ssh key into putty.ppk
format. Save.ppk
in$HOME/.ssh
.Start pageant (installed by putty installer). Add
.ppk
key file.If you’ve got the putty utilities on the path, check you can get authenticated e.g. into github with
plink git@github.com
. If you don’t have putty etc on the path, you’ll need the full path to plink, as in:"c:\Program files (x86)\Putty\plink git@github.com"
.Set a couple of environment variables from powershell - see powershell environment variables. First set
$GIT_SSH
to pick up plink as the ssh executable:[Environment]::SetEnvironmentVariable("GIT_SSH", "C:\Program files\Putty\plink.exe", "User")
Next we make sure that
$HOME
is set for safety. For example, setuptools appears to need it set correctly - see the example pypi page for the assertion at least:[Environment]::SetEnvironmentVariable("HOME", $env:USERPROFILE, "User")
Restart powershell after doing this to pick up the
GIT_SSH
environment variable in particular. We should now be able to do something likegit clone git@github.com:my-name/my-repo.git
without being asked our password (pageant handles this). The first time you use this combination with a particular host you may get an error like this:The server's host key is not cached in the registry. You have no guarantee that the server is the computer you think it is.
If so, run plink manually to cache the key:
& 'C:\Program Files (x86)\PuTTY\plink.exe' git@github.com
and press
y
when asked.I run pageant at startup. I first set up a desktop shortcut with the following command:
"C:\Program Files (x86)\PuTTY\pageant.exe" c:\Users\mb312\.ssh\id_dsa.ppk
I move this shortcut into my startup folder to start at login. On windows 7 my startup folder is:
C:\Users\mb312\AppData\Roaming\Microsoft\Windows\Start Menu\Programs\Startup
where
mb312
is my username.For using ssh inside the msysgit bash shell, I like to add the keychain-like script, by including this in my
~/.bashrc
file:# Source personal definitions if [ -f "$HOME/.bash_keychain_lite" ]; then . "$HOME/.bash_keychain_lite" fi
where the
.bash_keychain_lite
file arises from themake.py dotfiles
command above.
Miscellaneous¶
I got used to the mac keyboard way of using the command key for things like making new tabs in the browser (command-t), copy, paste (command-c, command-v) and so on. I can’t replicate all of this on windows, but as a first pass, I use an autohotkey script. Putting this
remap.ahk
script file into my Windows start menu startup folder caused it to be loaded at login:; From: http://superuser.com/questions/241889/macbook-pro-windows-7-remap-cmd-key-to-ctrl-except-cmdtab-to-alttab ; See also : http://www.autohotkey.com/docs/Hotkeys.htm ; # usually means Windows key. #SingleInstance force ; but sometimes # introduces a command #r::Send ^r ;reload #z::Send ^z ; undo #y::Send ^y ; redo #f::Send ^f ; find inside apps #g::Send ^g ; repeat find inside apps #c::Send ^c ; copy #x::Send ^x ; cut #v::Send ^v ; paste #a::Send ^a ; select all #t::Send ^t ; new tab in browser (IE, Safari, Firefox, etc) #s::Send ^s ; save inside apps LWin & Tab::AltTab ; the motherlode, alt-tab! #Up::Send {PgUp} ; PgUp #Down::Send {PgDn} ; PgDown #Left::Send {home} ; Home #Right::Send {end} ; End #LButton::^LButton
I depend heavily on knowing which branch I am on when using git. This is the what the
git-completion
bash routines do; posh-git does the equivalent for powershell.
Other programs¶
Install editor. I use vim. With a 64 bit python (below), I needed a 64 bit vim
Install python - the current version. I need this for the scripts installing the personal configuration below. For the convenience of using python at the command line you could do something like:
$my_path = [Environment]::GetEnvironmentVariable("PATH","User") $my_path += ";C:\Python27;C:\Python27\Scripts" [Environment]::SetEnvironmentVariable("PATH", $my_path, "User")
Set up personal configuration. For me this is:
cd c:\ mkdir code cd code mkdir dev_trees cd dev_trees git clone git@github.com:matthew-brett/myconfig.git git clone git@github.com:matthew-brett/myvim.git cd myconfig python make.py dotfiles cd ..\myvim python make.py vimfiles
I am trying out virtualenvwrapper-powershell . Install with the standard
python setup.py install
. You then needimport-module virtualenvwrapper
from the powershell prompt. Maybe it goes better in a powershell profile.As for any other environment, the nose-ipdb ipython debugger for nose makes debugging easier for nose tests. Easiest route is
easy_install ipdbplugin
.
Windows compiler and build tools¶
Download and install the mingw windows compiler. I used the
mingw-get-inst
automated installation route. Select the options giving you c++, fortran, and the msys build environment. I didn’t directly add these to the path, but made a scriptc:\Mingw\mingwvars.ps1
:# convenience script to add mingw to path echo "Adding mingw to PATH..." $mingw = [System.IO.Path]::GetDirectoryName($MyInvocation.MyCommand.Definition) $env:path = "$mingw\bin;$mingw\msys\1.0\bin;$env:path"
Then in powershell -
. c:\Mingw\mingwvars.ps1
to add the msys and mingw tools to the path.Using mingw, you might get this kind of error:
error: Setup script exited with error: Unable to find vcvarsall.bat
Of course you’ve already tried the standard solution to this, of the form:
python setup.py build --compiler=mingw32
If that doesn’t work, you might have hit a mingw distutils bug. One suggested fix is to make a
distutils.cfg
file in your Python distutils directory (e.g.C:\Python26\Lib\distutils
) with the following content:[build] compiler=mingw32
SWIG¶
Download the swig version for windows, swigwin
, from swig downloads,
unpack into, say, C:\
, then:
$my_path = [Environment]::GetEnvironmentVariable("PATH","User")
$my_path += ";C:\swigwin-2.0.10"
[Environment]::SetEnvironmentVariable("PATH", $my_path, "User")
[Environment]::SetEnvironmentVariable("PYTHON_INCLUDE", "C:\Python27\include", "User")
[Environment]::SetEnvironmentVariable("PYTHON_LIB", "C:\Python27\libs\python27.lib", "User")