76

I've just upgraded from Python 2.6.1 to 2.6.4 on my development machine and upon starting a python script was presented with the following message:

Can't extract file(s) to egg cache

The following error occurred while trying to extract file(s) to the Python egg cache:

[Errno 13] Permission denied: '/var/www/.python-eggs'

The Python egg cache directory is currently set to:

/var/www/.python-eggs

Perhaps your account does not have write access to this directory? You can change the cache directory by setting the PYTHON_EGG_CACHE environment variable to point to an accessible directory.

There isn't anything in the python docs so I'm at a bit of a loss regarding best-practices on where to put this directory and what it's used for.

Can someone explain what the Python egg cache is?

Also, can you explain why/how it is different to the site-packages directory Python uses to store eggs (as I understand it)?

Phillip B Oldham
  • 18,807
  • 20
  • 94
  • 134

9 Answers9

69

From my investigations it turns out that some eggs are packaged as zip files, and are saved as such in Python's site-packages directory.

These zipped eggs need to be unzipped before they can be executed, so are expanded into the PYTHON_EGG_CACHE directory which by default is ~/.python-eggs (located in the user's home directory). If this doesn't exist it causes problems when trying to run applications.

There are a number of fixes:

  1. Create a .python-eggs directory in the user's home directory and make it writable for the user.
  2. Create a global directory for unzipping (eg. /tmp/python-eggs) and set the environment variable PYTHON_EGG_CACHE to this directory.
  3. Use the -Z switch when using easy_install to unzip the package when installing.
Phillip B Oldham
  • 18,807
  • 20
  • 94
  • 134
  • 8
    Python can access files inside .zip files. The only time that they need to be extracted is when the application wants a filename instead of a file-like object for a resource (or directory) inside an egg. This usually happens with web servers and the like. – wump Mar 31 '11 at 16:16
  • 2
    Worth mentioning as well that .python-eggs takes your umask without adding execution permissions onto the directory. Directories are not accessible without execution permissions, so you get the same error as above. – joedborg Mar 29 '13 at 16:16
  • 1
    I wonder why it would be set to `/var/www/.python-eggs` by default and not somewhere more standard-looking.... – tutuca Sep 06 '14 at 19:08
  • 3
    +1 for Option 3. This bugged me out for hours today. Using easy_install with the -Z option solved my problem in seconds. Easy_install, it's not so easy. – Dennis Bauszus May 29 '15 at 00:52
30

The python egg cache is simply a directory used by setuptools to store packages installed that conform to the egg specification. You can read more about setuptools here.

Additionally, as the error message states, you can specify a different egg cache directory in your environment by setting PYTHON_EGG_CACHE=/some/other/dir. The easiest way to do this is to set it in your ~/.bash_profile (assuming you're using bash), like this:

export PYTHON_EGG_CACHE=/some/other/dir

You may need to set it in your Apache environment if you're using a Web application.

AJ.
  • 27,586
  • 18
  • 84
  • 94
  • I solved a missing environment variable in Google App Engine's web server by editing app.yaml like this: env_variables: PYTHON_EGG_CACHE: 'C:\Python27\Lib\site-packages' https://stackoverflow.com/questions/31122337/does-google-app-engine-support-environment-variables/31123599#31123599 – dbasch Dec 11 '15 at 13:47
14

This is a dark side-effect of using otherwise nice eggs mechanism.

Eggs are packages (a directory full of files) packed into one .egg file to simplify depolyment.

They are stored in /site-packages/ dir.

As long as the files stored in the egg are .py files it works great. Python import can import things from any file-like object just like it was an ordinary file.

But when something like .so happens to drop in there, python cannot explain to the underlying OS that it wants to load an library which doesn't have a physical name. And the only workaround distutils authors have thought of is unzipping it into a temp dir. Naturally it is not /site-packages/ since /site-packages/ is not writable for ordinary users.

So you can either

  • set PYTHON_EGG_DIR to /tmp, or

  • give user www write permission to /var/www/.python-eggs
    (so that the files don't get unzipped every time /tmp is cleaned up) or better then

  • unzip the egg as suggested by @shalley303
    (and avoid unzipping of the egg in the run-time altogether).

Antony Hatchkins
  • 31,947
  • 10
  • 111
  • 111
3

You can also disable the use of the .egg after it has been installed. You need to go into the site-packages directory, extract the .egg, and then move it to a hidden file (or delete it, or whatever).

Here is an example of what I did to disable the MySQLdb module .egg file which was causing this error when the python script was being run from Zabbix.

cd /usr/local/lib/python2.7/site-packages
unzip MySQL_python-1.2.3-py2.7-linux-x86_64.egg
mv MySQL_python-1.2.3-py2.7-linux-x86_64.egg .MySQL_python-1.2.3-py2.7-linux-x86_64.egg
shalley303
  • 31
  • 2
  • I don't think you get a `.egg` with PyODBC, just a `.egg-info` and `.so` – joedborg Apr 01 '13 at 09:31
  • This works for me if instead of moving ``MySQL_python-1.2.3-py2.7-linux-x86_64.egg`` to ``.MySQL_python-1.2.3-py2.7-linux-x86_64.egg`` I move the unzipped ``EGG-INFO`` file to ``MySQL_python-1.2.3-py2.7-linux-x86_64.egg-info`` – Mike D Apr 04 '16 at 22:57
3

Python eggs are zip-compressed packages containing both Python modules and metadata. The egg cache is where the extracted contents of the egg are stored so that the Python modules contained within are usable.

HoldOffHunger
  • 18,769
  • 10
  • 104
  • 133
Ignacio Vazquez-Abrams
  • 776,304
  • 153
  • 1,341
  • 1,358
2

Phillip B Oldham's right. You can add these lines in your code:

import os  
os.environ['PYTHON_EGG_CACHE'] = '/tmp' # a writable directory 
Codefor
  • 1,318
  • 2
  • 13
  • 22
0

A simple fix would be to create the directory and provide www-data access to it.

$ mkdir /var/www/.python-eggs
$ chown www-data:www-data /var/www/.python-eggs
Bilal Baqar
  • 208
  • 2
  • 12
0

I got this error in Django when running the below command the first time.

python manage.py sql myproject

I got it to work like this:

1. In Explorer, view the folder that the error says egg cache directory is set to
2. Delete (or rename) the file mysql_python-1.2.5-py2.7-win32.egg-tmp
3. That's it. The command now works and creates a new file in there. (Haven't tested if I need to do this every time.)
user984003
  • 28,050
  • 64
  • 189
  • 285
0

adding this at the begin of my source file before any import works

import os
xyz = os.path.join('~', 'Documents', '.cache')
os.environ['PYTHON_EGG_CACHE'] = os.path.expanduser(xyz)
Garantor
  • 27
  • 3