'Update scrapy settings based on spider property

Is there a way with scrapy to dynamically set the settings for a spider given at runtime? I want to add an isDebug variable to my spider and depending on it's value I want to adjust log level, pipelines and various other settings ...

When trying to manipulate the settings as said in the manual, like this:

    def from_crawler(cls, crawler):
        settings = crawler.settings
        settings['USER_AGENT'] = 'Overwridden-UA'

I always get TypeError: Trying to modify an immutable Settings object



Solution 1:[1]

Settings object is immutable by itself, but has number of set methods, for ex settings.set https://github.com/scrapy/scrapy/blob/129421c7e31b89b9b0f9c5f7d8ae59e47df36091/scrapy/settings/init.py#L234

Recent versions of Scrapy (beginning from 1.0) spiders has class method update_settings

@classmethod
def update_settings(cls, settings):
    settings.setdict(cls.custom_settings or {}, priority='spider')

which is intended to override settings with ones presented in custom_settings property of the spider. So to reach your goal you can override that method in some way like that

class TheSpider(scrapy.Spider):
    name = 'thespider'
    is_debug = True
    custom_debug_settings = {
       # Put your debug settings here
    }

    @classmethod
    def update_settings(cls, settings):
        settings.setdict(getattr(cls, 'custom_debug_settings' \
                                      if getattr(cls, 'is_debug', False) \
                                      else 'custom_settings', None) or {},
                         priority='spider')

And of course there is project-wide 'two scoops of Django' way to have custom settings file for debug purposes, so it could be something like that:

settings.py (add to the end of the file):

try:
    from dev_settings import *
except ImportError:
    pass

then you can create dev_settings.py next to settings.py and add there settings you'd like to customize for your development purposes - them will be overwritten if dev_settings.py exists or import will be just ignored if not.

Solution 2:[2]

Hope this is helpful as well since this is what I needed and what actually worked for me for my use-case where I too had a few set of settings that I wanted updated in the custom spider settings on runtime (Note: Answer inpired by mizhgun, thanks to mizhgun, @stackoverflow and the whole dev community)

settings_to_be_updated = {
    'USER_AGENT': 'Overwridden-UA',
}

class SpiderName(scrapy.Spider):
    name = 'spider_name'
    is_debug = True
    custom_settings = {
       # Put your all your custom settings here
    }

    @classmethod
    def update_settings(cls, settings):
        cls.custom_settings.update(settings_to_be_updated)
        settings.setdict(cls.custom_settings or {}, priority='spider')

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 mizhgun
Solution 2 dhruv sharma