Why was an old .pyc file breaking Django?
I pulled the latest code using git today and I got the following error:
ImportError at / cannot import name Like
This might have something to do with circular imports. I examined the traceback:
Traceback: File "/Library/Python/2.7/site-packages/Django-1.4.1-py2.7.egg/django/core/handlers/base.py" in get_response 101. request.path_info) File "/Library/Python/2.7/site-packages/Django-1.4.1-py2.7.egg/django/core/urlresolvers.py" in resolve 298. for pattern in self.url_patterns: File "/Library/Python/2.7/site-packages/Django-1.4.1-py2.7.egg/django/core/urlresolvers.py" in url_patterns 328. patterns = getattr(self.urlconf_module, "urlpatterns", self.urlconf_module) File "/Library/Python/2.7/site-packages/Django-1.4.1-py2.7.egg/django/core/urlresolvers.py" in urlconf_module 323. self._urlconf_module = import_module(self.urlconf_name) File "/Library/Python/2.7/site-packages/Django-1.4.1-py2.7.egg/django/utils/importlib.py" in import_module 35. __import__(name) File "/Users/Desktop/python/mystuff/Project/Project/urls.py" in <module> 7. admin.autodiscover() File "/Library/Python/2.7/site-packages/Django-1.4.1-py2.7.egg/django/contrib/admin/__init__.py" in autodiscover 29. import_module('%s.admin' % app) File "/Library/Python/2.7/site-packages/Django-1.4.1-py2.7.egg/django/utils/importlib.py" in import_module 35. __import__(name)
The only code in there it looked that could be causing the problem was urls.py. That had the following code:
from django.contrib import admin admin.autodiscover()
So around this time I notice that the admin.py file that we previously had written was deleted in the latest merge but that the admin.pyc still existed. Deleting the .pyc file proceeded to fix the circular import error and now things seem to work fine.
My question is: what exactly was happening here? Git is configured to ignore all pyc files so after the merge the .pyc stuck around even though the .py was removed. But shouldn't python be smart enough not to try to call any compiled code in the .pyc if the .py itself was deleted?
No, in fact, Python will use the .pyc file preferably and only access the .py file if it a) exists and b) is newer than the .pyc file.
This allows you to distribute a Python app in compiled form without the source code (although it's not much of a code "obfuscation" technique).