Ran into a problem while attempting to get Python provisioned automatically in Windows. I could install Python as an administrator, but when I would switch into a Limited User Account and attempt to use pip
or virtualenv
, I’d get nothing but obscure failure.
The key phrase that kept popping up was:
“WindowsError: [Error 183] Cannot create a file when that file already exists: ‘C:\\Documents and Settings\\Administrator\\.distlib'”
as distlib
kept trying to put things into the admin account by default.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 |
C:\provision-windows-master>pip install virtualenv Traceback (most recent call last): File "c:\Python27\Scripts\pip-script.py", line 9, in <module> load_entry_point('pip==1.5', 'console_scripts', 'pip')() File "build\bdist.win32\egg\pkg_resources.py", line 353, in load_entry_point File "build\bdist.win32\egg\pkg_resources.py", line 2302, in load_entry_point File "build\bdist.win32\egg\pkg_resources.py", line 2029, in load File "C:\Python27\lib\site-packages\pip\__init__.py", line 11, in <module> from pip.vcs import git, mercurial, subversion, bazaar # noqa File "C:\Python27\lib\site-packages\pip\vcs\subversion.py", line 4, in <module> from pip.index import Link File "C:\Python27\lib\site-packages\pip\index.py", line 16, in <module> from pip.wheel import Wheel, wheel_ext, wheel_setuptools_support File "C:\Python27\lib\site-packages\pip\wheel.py", line 23, in <module> from pip._vendor.distlib.scripts import ScriptMaker File "C:\Python27\lib\site-packages\pip\_vendor\distlib\scripts.py", line 15, in <module> from .resources import finder File "C:\Python27\lib\site-packages\pip\_vendor\distlib\resources.py", line 105, in <module> cache = Cache() File "C:\Python27\lib\site-packages\pip\_vendor\distlib\resources.py", line 40, in __init__ base = os.path.join(get_cache_base(), 'resource-cache') File "C:\Python27\lib\site-packages\pip\_vendor\distlib\util.py", line 602, in get_cache_base os.makedirs(result) File "C:\Python27\lib\os.py", line 157, in makedirs mkdir(name, mode) WindowsError: [Error 183] Cannot create a file when that file already exists: 'C:\\Documents and Settings\\Strong\\.distlib' |
To make sense of the error, I had to dig into the closest code to the WindowsError
that was thrown, which looked like this:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 |
def get_cache_base(suffix=None): """ Return the default base location for distlib caches. If the directory does not exist, it is created. Use the suffix provided for the base directory, and default to '.distlib' if it isn't provided. On Windows, if LOCALAPPDATA is defined in the environment, then it is assumed to be a directory, and will be the parent directory of the result. On POSIX, and on Windows if LOCALAPPDATA is not defined, the user's home directory - using os.expanduser('~') - will be the parent directory of the result. The result is just the directory '.distlib' in the parent directory as determined above, or with the name specified with ``suffix``. """ if suffix is None: suffix = '.distlib' if os.name == 'nt' and 'LOCALAPPDATA' in os.environ: result = os.path.expandvars('$localappdata') else: # Assume posix, or old Windows result = os.path.expanduser('~') result = os.path.join(result, suffix) # we use 'isdir' instead of 'exists', because we want to # fail if there's a file with that name if not os.path.isdir(result): os.makedirs(result) return result |
Lo and behold, setting the LOCALAPPDATA
environment variable to some writeable folder to which the Limited user has acccess will fix the issue. But it strikes me as a place where the os.path.expandvars()
call should probably check the APPDATA
environment variable too.
And, for whatever odd reason, it seems like the os.path.expanduser() call uses the user credentials associated with the Python executable or something, because at no point as I’m running this code as a Limited User, do I specify that I want the code to act like it is an Administrator. It’s a bit odd.
1 2 3 4 5 6 7 8 |
C:\Documents and Settings\Limited\Desktop>set APPDATA=C:\Documents and Settings\Limited\Application Data C:\Documents and Settings\Limited\Desktop>set LOCALAPPDATA=%APPDATA% C:\Documents and Settings\Limited\Desktop>virtualenv venv New python executable in venv\Scripts\python.exe Installing setuptools, pip...done. |
In any case, it works, but the solution is less than obvious.