Channels: runserver raise error.ReactorAlreadyInstalledError("reactor already installed")

Created on 3 Feb 2018  路  23Comments  路  Source: django/channels

Now I add channels to project by installation guide from docs

  • OS and runtime environment
    virtualenv with Python 3.5.3 [GCC 6.3.0 20170118] on linux / debian Jessie
  • The versions of Channels, Daphne, Django, Twisted
    daphne==2.0.0
    Django==2.0.2
    Twisted==17.9.0

  • What you expected to happen vs. what actually happened
    python src/manage.py runserver 8925
    and get raise error.ReactorAlreadyInstalledError("reactor already installed")

  • How you're running Channels (runserver? daphne/runworker? Nginx/Apache in front?)
    on localhost just
    python src/manage.py runserver 8925

  • Console logs and full tracebacks of any errors

$ ls src
apps
project_src 
manage.py  

$ ls src/project_src/
asgi.py  
__init__.py  
locale
routing.py
settings  
static  
templates  
urls.py  
wsgi.py

ROOT_URLCONF = 'project_src.urls'
WSGI_APPLICATION = 'project_src.wsgi.application'
ASGI_APPLICATION = "project_src.routing.application"

(.venv3) berg@berg-dell:/Working-dir/$python src/manage.py runserver 8925
Unhandled exception in thread started by <function check_errors.<locals>.wrapper at 0x7f4155431e18>
Traceback (most recent call last):
  File "/Working-dir/.venv3/lib/python3.5/site-packages/django/utils/autoreload.py", line 225, in wrapper
    fn(*args, **kwargs)
  File "/Working-dir/.venv3/lib/python3.5/site-packages/django/core/management/commands/runserver.py", line 113, in inner_run
    autoreload.raise_last_exception()
  File "/Working-dir/.venv3/lib/python3.5/site-packages/django/utils/autoreload.py", line 248, in raise_last_exception
    raise _exception[1]
  File "/Working-dir/.venv3/lib/python3.5/site-packages/django/core/management/__init__.py", line 327, in execute
    autoreload.check_errors(django.setup)()
  File "/Working-dir/.venv3/lib/python3.5/site-packages/django/utils/autoreload.py", line 225, in wrapper
    fn(*args, **kwargs)
  File "/Working-dir/.venv3/lib/python3.5/site-packages/django/__init__.py", line 24, in setup
    apps.populate(settings.INSTALLED_APPS)
  File "/Working-dir/.venv3/lib/python3.5/site-packages/django/apps/registry.py", line 89, in populate
    app_config = AppConfig.create(entry)
  File "/Working-dir/.venv3/lib/python3.5/site-packages/django/apps/config.py", line 116, in create
    mod = import_module(mod_path)
  File "/Working-dir/.venv3/lib/python3.5/importlib/__init__.py", line 126, in import_module
    return _bootstrap._gcd_import(name[level:], package, level)
  File "<frozen importlib._bootstrap>", line 986, in _gcd_import
  File "<frozen importlib._bootstrap>", line 969, in _find_and_load
  File "<frozen importlib._bootstrap>", line 958, in _find_and_load_unlocked
  File "<frozen importlib._bootstrap>", line 673, in _load_unlocked
  File "<frozen importlib._bootstrap_external>", line 673, in exec_module
  File "<frozen importlib._bootstrap>", line 222, in _call_with_frames_removed
  File "/Working-dir/.venv3/lib/python3.5/site-packages/channels/apps.py", line 6, in <module>
    import daphne.server  # noqa
  File "/Working-dir/.venv3/lib/python3.5/site-packages/daphne/server.py", line 3, in <module>
    asyncioreactor.install()  # isort:skip
  File "/Working-dir/.venv3/lib/python3.5/site-packages/twisted/internet/asyncioreactor.py", line 322, in install
    installReactor(reactor)
  File "/Working-dir/.venv3/lib/python3.5/site-packages/twisted/internet/main.py", line 32, in installReactor
    raise error.ReactorAlreadyInstalledError("reactor already installed")
twisted.internet.error.ReactorAlreadyInstalledError: reactor already installed

Most helpful comment

import channels.apps

?

All 23 comments

Hi,

Please, check out you have settings.INSTALLED_APPS set properly. Channels will try to initiate twisted reactor early in the app config.

https://github.com/django/channels/blob/master/channels/apps.py

I was try comment all 3-rd apps and set only

INSTALLED_APPS = [
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.sites',
    'django.contrib.sitemaps',
    'django.contrib.staticfiles',
    'django.contrib.gis',
    'channels',
]

but have same error

Something in your code install twisted reactor before channels got to it. What is the way you run channels?

I just completed this instruction and wanted to check it out
https://channels.readthedocs.io/en/latest/installation.html

Now I was try start new project myproject with virtualenv with Python 3.5.3 for test
according to the instructions and everything works... I will seek that which is not so in a working project.

Yes, as @proofit404 says, this is caused by something else initialising Twisted before Channels even gets imported (where we try to initialise it as soon as that happens). There might be other installed packages that aren't interfering in a virtualenv - I'd try a fresh virtualenv and just install Channels and see if it still happens.

I've tried recreating the problem with the package versions you specify, and I can't make it fail, so I'm going to close this for now as it seems to be a problem on your end. If we determine it's actually an issue in Channels we can re-open it with more info.

(Relatedly, I'd love to find a way to get Twisted to tell you where the previous import happened from but sadly that does not seem possible)

the problem was in the configuration sentry logger https://docs.sentry.io/clients/python/integrations/django/

localy I disable raven, but sentry config was stay exists in LOGGING setting
after comment this section, all worked

    'handlers': {
#         'sentry': {
#             'level': 'ERROR',  # To capture more than ERROR, change to WARNING, INFO, etc.
#             'class': 'raven.contrib.django.raven_compat.handlers.SentryHandler',
#             'tags': {'custom-tag': 'x'},
#         },

Oof, if it's in sentry/raven a lot of people are going to run into this.

Yup, looks like Raven has a Twisted transport we're going to have to work out how to deconflict with: https://github.com/getsentry/raven-python/blob/17b823d69b70d8a92982b140a1763a84905faeb2/raven/transport/twisted.py

As a workaround for now, you should be able to fix it by adding an import channels to the top of your settings file?

adding an import channels to the top of my settings file don't work. stay have same error.

import channels.apps

?

This problem happens when you try to embed Channels in a normal Twisted application too.

Something that relies on

import sys
sys.modules['twisted.internet.reactor']

being the correct reactor would solve my issues, i.e. install reactor if none found, continue if correct found.

I think most of the times it will be the default twisted reactor for the current platform. But channels relies on the asyncio.

The only way to fix it right now is to edit Daphne source code which isn't all that nice. By adding functionality as I outlined it'd be possible to add a reactor installation somewhere early in your application.

Does import daphne early in your code solves the problem?

I try add to the top of my settings file
import channels.apps
As a workaround for now it worked with sentry part in LOGGING.
Thanks!

Yes, we can't just use the default Twisted reactor, we _need_ the asyncio one. I'll look today into at least improving the error message, if not finding a way to uninstall previous reactors (which you're not meant to do, but...)

I don't think it is possible to uninstall twisted reactor. You can't even stop it and run the second time.

There are ways and means, the question is if they're stable and useful.

Yeh... Cleanup is always harder than pollution.

First attempt at fixing this is in django/daphne@7949b24, it seems to work in local testing...

The fix strikes me as a weird way to solve the issue.

In making something that is not suppose to rely on channels or daphne I'm forced to rely on both to ensure I can support them in the first place.

The first thing my daphne replacement does is import daphne to make sure it doesn't mess stuff up, loading anything ASGI related later during runtime is completely out of the picture.

All it has to do is to check if the correct reactor is loaded instead of always unloading what is already there.

Something along the lines

import sys  # isort:skip
import warnings  # isort:skip
from twisted.internet import asyncioreactor  # isort:skip
from twisted.internet.asyncioreactor import AsyncioSelectorReactor  # isort:skip
if "twisted.internet.reactor" in sys.modules and not isinstance(sys.modules["twisted.internet.reactor"], AsyncioSelectorReactor):
    warnings.warn(
        "Something has already installed a Twisted reactor. Attempting to uninstall it; " +
        "you can fix this warning by importing daphne.server early in your codebase or " +
        "finding the package that imports Twisted and importing it later on.",
        UserWarning,
    )
    del sys.modules["twisted.internet.reactor"]
if "twisted.internet.reactor" not in sys.modules:
    asyncioreactor.install()

That's fair - I had a first version that just looked for the AlreadyInstalledError, which would work too, but I moved it for brevity. I'll restore that and put it all in a function.

OK, the latest commit (https://github.com/django/daphne/commit/826a8ce0de9ca33ed324bd6e9a7d43679bb1a2a9) does this.

Was this page helpful?
0 / 5 - 0 ratings

Related issues

djangojack picture djangojack  路  19Comments

andrewgodwin picture andrewgodwin  路  24Comments

davidfstr picture davidfstr  路  18Comments

ahaltindis picture ahaltindis  路  41Comments

andrewgodwin picture andrewgodwin  路  54Comments