2012-09-08 9 views
9

me sacó el último código usando git hoy y me dieron el siguiente error:¿Por qué un antiguo archivo .pyc rompía Django?

ImportError at/
cannot import name Like 

Esto podría tener algo que ver con las importaciones circulares. Examiné el rastreo:

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) 

El único código de allí parecía que podría estar causando el problema era urls.py. Eso tuvo el siguiente código:

from django.contrib import admin 
admin.autodiscover() 

Así que en todo este tiempo me di cuenta de que el archivo admin.py que previamente habíamos escrito se ha eliminado en la última fusión, pero que todavía existía la admin.pyc. Al eliminar el archivo .pyc se corrigió el error circular de importación y ahora todo parece funcionar bien.

Mi pregunta es: ¿qué estaba pasando exactamente aquí? Git está configurado para ignorar todos los archivos pyc, por lo que después de la fusión, el .pyc se mantuvo aunque se eliminó .pyc. Pero, ¿no debería Python ser lo suficientemente inteligente como para no intentar llamar a ningún código compilado en el .pyc si se eliminó el .py mismo?

+0

No sabe que se eliminó, y en realidad siempre trata de usar 'pyc' si no hay' py' o si 'py' es anterior. –

+0

Agregue esto a su archivo 'root_directory/.gitignore':' * .pyc'. Le dirá a git que ignore los bytecodes de Python. No es una buena idea tener 'pyc' para ser parte del repositorio, ya que cada característica local los editaría, y podría llevar a errores de tiempo de ejecución si los empuja a otros que no tienen sus nuevos módulos. –

Respuesta

8

No, de hecho, Python utilizará el archivo .pyc preferencia y sólo acceder al archivo .py si a) existe y b) es más reciente que el archivo .pyc.

Esto le permite distribuir una aplicación de Python en forma compilada sin el código fuente (aunque no es una técnica de "ofuscación" de código).

+1

Esta característica también permite a las distribuciones de Linux tener los archivos '.py' de paquetes instalados en un solo lugar y poner los archivos' .pyc' en el directorio 'lib' de cada versión de Python (que es quizás una aplicación más útil). –

2

Lo que puede hacer para evitar que esto es empezar a Django con

python -B manage.py runserver 

o para automatizar la eliminación de PYC, probablemente con clean_pyc de Django extensiones

./manage.py clean_pyc 
4

No, Python es (intencionalmente, ver abajo) ¡tonto sobre esto! Puede ejecutar

find . -name '*.pyc' -delete 

desde el directorio del proyecto para deshacerse de los viejos .pyc archivos.

Si está utilizando git, puede set up a hook para hacerlo automáticamente en el proceso de pago. Aquí hay un similar solution para Mercurial.

+2

No llamaría a esto "tonto". Fue una decisión de diseño intencional para respaldar esto, y tiene varios casos de uso. Es una característica. –

Cuestiones relacionadas