This is very old issue in Django: see ticket
https://code.djangoproject.com/ticket/8280
I've attached the patch I'm already using for years to package my django
application with py2exe.
I don't understand why the core team continues to use the current
un-pythonic code to discover commands and fails to merge any of the fixes
that have been proposed.
Johan
Op donderdag 10 april 2014 14:19:19 UTC+2 schreef Antonio Francisco Martín
Romero:
>
> Hi everyone,
>
> I was using py2exe + Django 1.3 without problems. From Django 1.4 the way
> to find the commands changed and it tries to find .py files as you can see
> in the find_commands() function in the file core/management/__init__.py .
> When you compile Django using py2exe, your don't have .py files, just .pyc
> and manage.exe won't have any command. I have tried to modify the
> find_command() function but the result was negative. Also, I have tried to
> run commands manually but the functions try to find .py files as well.
>
> Did anyone manage to do it?
>
> Cheers
>
--
You received this message because you are subscribed to the Google Groups
"Django users" group.
To unsubscribe from this group and stop receiving emails from it, send an email
to [email protected].
To post to this group, send email to [email protected].
Visit this group at http://groups.google.com/group/django-users.
To view this discussion on the web visit
https://groups.google.com/d/msgid/django-users/71e4944c-0b0c-4939-8514-10da0a4d667e%40googlegroups.com.
For more options, visit https://groups.google.com/d/optout.
django/core/management/__init__.py | 62 +++++++++-----------------------------
1 file changed, 14 insertions(+), 48 deletions(-)
diff --git a/django/core/management/__init__.py b/django/core/management/__init__.py
index 5b0ad6c..62f0796 100644
--- a/django/core/management/__init__.py
+++ b/django/core/management/__init__.py
@@ -3,11 +3,14 @@ import os
import sys
from optparse import OptionParser, NO_DEFAULT
import imp
+import warnings
+from pkgutil import iter_modules
from django.core.exceptions import ImproperlyConfigured
from django.core.management.base import BaseCommand, CommandError, handle_default_options
from django.core.management.color import color_style
from django.utils.importlib import import_module
+from django.utils._os import upath
from django.utils import six
# For backwards compatibility: get_version() used to be in this module.
@@ -17,54 +20,18 @@ from django import get_version
# doesn't have to reload every time it's called.
_commands = None
-def find_commands(management_dir):
+def find_commands(app_name):
"""
- Given a path to a management directory, returns a list of all the command
- names that are available.
+ Given an application name, returns a list of all the commands found.
- Returns an empty list if no commands are defined.
+ Raises ImportError if no commands are defined.
"""
- command_dir = os.path.join(management_dir, 'commands')
- try:
- return [f[:-3] for f in os.listdir(command_dir)
- if not f.startswith('_') and f.endswith('.py')]
- except OSError:
- return []
-
-def find_management_module(app_name):
- """
- Determines the path to the management module for the given app_name,
- without actually importing the application or the management module.
-
- Raises ImportError if the management module cannot be found for any reason.
- """
- parts = app_name.split('.')
- parts.append('management')
- parts.reverse()
- part = parts.pop()
- path = None
-
- # When using manage.py, the project module is added to the path,
- # loaded, then removed from the path. This means that
- # testproject.testapp.models can be loaded in future, even if
- # testproject isn't in the path. When looking for the management
- # module, we need look for the case where the project name is part
- # of the app_name but the project directory itself isn't on the path.
- try:
- f, path, descr = imp.find_module(part, path)
- except ImportError as e:
- if os.path.basename(os.getcwd()) != part:
- raise e
- else:
- if f:
- f.close()
-
- while parts:
- part = parts.pop()
- f, path, descr = imp.find_module(part, [path] if path else None)
- if f:
- f.close()
- return path
+ packages = {}
+ mgmt_package = "%s.management.commands" % app_name
+ # The next line imports the *package*, not all modules in the package
+ __import__(mgmt_package)
+ path = getattr(sys.modules[mgmt_package], '__path__', None)
+ return [i[1] for i in iter_modules(path)]
def load_command_class(app_name, name):
"""
@@ -99,7 +66,7 @@ def get_commands():
"""
global _commands
if _commands is None:
- _commands = dict([(name, 'django.core') for name in find_commands(__path__[0])])
+ _commands = dict([(name, 'django.core') for name in find_commands('django.core')])
# Find the installed apps
from django.conf import settings
@@ -113,9 +80,8 @@ def get_commands():
# Find and load the management module for each installed app.
for app_name in apps:
try:
- path = find_management_module(app_name)
_commands.update(dict([(name, app_name)
- for name in find_commands(path)]))
+ for name in find_commands(app_name)]))
except ImportError:
pass # No management module - ignore this app