Browse Source

Explain problem with relative imports and module imports. Closes celery/django-celery#99

Ask Solem 11 years ago
parent
commit
ba1ea77c7d
1 changed files with 47 additions and 15 deletions
  1. 47 15
      docs/userguide/tasks.rst

+ 47 - 15
docs/userguide/tasks.rst

@@ -157,31 +157,63 @@ For example if the client imports the module "myapp.tasks" as ".tasks", and
 the worker imports the module as "myapp.tasks", the generated names won't match
 the worker imports the module as "myapp.tasks", the generated names won't match
 and an :exc:`~@NotRegistered` error will be raised by the worker.
 and an :exc:`~@NotRegistered` error will be raised by the worker.
 
 
-This is also the case if using Django and using `project.myapp`::
+This is also the case when using Django and using `project.myapp`-style
+naming in ``INSTALLED_APPS``:
 
 
-    INSTALLED_APPS = ('project.myapp', )
+.. code-block:: python
+
+    INSTALLED_APPS = ['project.myapp']
 
 
-The worker will have the tasks registered as "project.myapp.tasks.*",
-while this is what happens in the client if the module is imported as
-"myapp.tasks":
+If you install the app under the name ``project.myapp`` then the
+tasks module will be imported as ``project.myapp.tasks``,
+so you must make sure you always import the tasks using the same name:
 
 
 .. code-block:: python
 .. code-block:: python
 
 
-    >>> from myapp.tasks import add
-    >>> add.name
-    'myapp.tasks.add'
+    >>> from project.myapp.tasks import mytask   # << GOOD
+
+    >>> from myapp.tasks import mytask    # << BAD!!!
+
+The second example will cause the task to be named differently
+since the worker and the client imports the modules under different names:
+
+.. code-block:: python
+
+    >>> from project.myapp.tasks import mytask
+    >>> mytask.name
+    'project.myapp.tasks.mytask'
+
+    >>> from myapp.tasks import mytask
+    >>> mytask.name
+    'myapp.tasks.mytask'
+
+So for this reason you must be consistent in how you
+import modules, which is also a Python best practice.
 
 
-For this reason you should never use "project.app", but rather
-add the project directory to the Python path::
+Similarly, you should not use old-style relative imports:
 
 
-    import os
-    import sys
-    sys.path.append(os.path.dirname(os.path.realpath(__file__)))
+.. code-block:: python
+
+    from module import foo   # BAD!
+
+    from proj.module import foo  # GOOD!
+
+New-style relative imports are fine and can be used:
+
+.. code-block:: python
+
+    from .module import foo  # GOOD!
 
 
-    INSTALLED_APPS = ('myapp', )
+If you want to use Celery with a project already using these patterns
+extensively and you don't have the time to refactor the existing code
+then you can consider specifying the names explicitly instead of relying
+on the automatic naming:
 
 
-This makes more sense from the reusable app perspective anyway.
+.. code-block:: python
 
 
+    @task(name='proj.tasks.add')
+    def add(x, y):
+        return x + y
 
 
 .. _task-request-info:
 .. _task-request-info: