title: APScheduler Look up object error
body: <p>APScheduler (3.3.1)  py2.7</p>
  
  <p>I use this code to do my job When I use Memory as job store it can work well but I have too many job and my Memory in server is limit so I change SQLAlchemyJobStore as job store but I got the Lookup error. How to solve it.</p>
  
  <p>Code:</p>
  
  <pre><code>def script(indicator, strategy_name, real_time=False):
      # Solve No handlers could be found for logger “apscheduler.scheduler
      import logging
      logging.basicConfig(level=logging.ERROR,
                          format='%(name)-12s %(asctime)s %(levelname)-8s %(message)s',
                          datefmt='%a, %d %b %Y %H:%M:%S')
      try:
          job_defaults = {
              'coalesce': False,
              'max_instances': 1,
              "misfire_grace_time": config.real_time_script_interval + 5,
          }
          executors = {
              'default': ThreadPoolExecutor(60),
          }
          jobstores = {
              "default": SQLAlchemyJobStore(url='sqlite:///jobs.sqlite')
          }
  
          scheduler = BlockingScheduler(daemonic=True, jobstores=jobstores, job_defaults=job_defaults,
                                        executors=executors)
          module = __import__("%s.%s" % (indicator, strategy_name), fromlist=[strategy_name])
          if real_time:
              for st in module.strategy:
                  scheduler.add_job(st.run, "interval", seconds=config.real_time_script_interval)
          else:
              for st in module.strategy:
                  # 计算最近的下一个准点时间
                  start_time = _recent_time(st.run_period)
                  scheduler.add_job(st.run, "interval", **start_time)
          scheduler.start()
      except Exception as e:
          logger.get("run-log").error(error_msg())
  </code></pre>
  
  <p>Error:</p>
  
  <pre><code>apscheduler.jobstores.default Thu, 06 Apr 2017 10:50:32 ERROR    Unable to restore job "d100a4b24e2d49c3ad51305fd846e5f5" -- removing it
  Traceback (most recent call last):
    File "/Users/wyx/bitcoin_workspace/fibo-strategy/.env/lib/python2.7/site-packages/apscheduler/jobstores/sqlalchemy.py", line 135, in _get_jobs
      jobs.append(self._reconstitute_job(row.job_state))
    File "/Users/wyx/bitcoin_workspace/fibo-strategy/.env/lib/python2.7/site-packages/apscheduler/jobstores/sqlalchemy.py", line 122, in _reconstitute_job
      job.__setstate__(job_state)
    File "/Users/wyx/bitcoin_workspace/fibo-strategy/.env/lib/python2.7/site-packages/apscheduler/job.py", line 260, in __setstate__
      self.func = ref_to_obj(self.func_ref)
    File "/Users/wyx/bitcoin_workspace/fibo-strategy/.env/lib/python2.7/site-packages/apscheduler/util.py", line 277, in ref_to_obj
      raise LookupError('Error resolving reference %s: error looking up object' % ref)
  LookupError: Error resolving reference base.strategy:Strategy.run: error looking up object
  apscheduler.jobstores.default Thu, 06 Apr 2017 10:50:32 ERROR    Unable to restore job "2602167cd3c745c2b0764a2b63da1a3a" -- removing it
  Traceback (most recent call last):
    File "/Users/wyx/bitcoin_workspace/fibo-strategy/.env/lib/python2.7/site-packages/apscheduler/jobstores/sqlalchemy.py", line 135, in _get_jobs
      jobs.append(self._reconstitute_job(row.job_state))
    File "/Users/wyx/bitcoin_workspace/fibo-strategy/.env/lib/python2.7/site-packages/apscheduler/jobstores/sqlalchemy.py", line 122, in _reconstitute_job
      job.__setstate__(job_state)
    File "/Users/wyx/bitcoin_workspace/fibo-strategy/.env/lib/python2.7/site-packages/apscheduler/job.py", line 260, in __setstate__
      self.func = ref_to_obj(self.func_ref)
    File "/Users/wyx/bitcoin_workspace/fibo-strategy/.env/lib/python2.7/site-packages/apscheduler/util.py", line 277, in ref_to_obj
      raise LookupError('Error resolving reference %s: error looking up object' % ref)
  LookupError: Error resolving reference base.strategy:Strategy.run: error looking up object
  apscheduler.jobstores.default Thu, 06 Apr 2017 10:50:32 ERROR    Unable to restore job "3eb917670e7642b8848a165268df8913" -- removing it
  Traceback (most recent call last):
    File "/Users/wyx/bitcoin_workspace/fibo-strategy/.env/lib/python2.7/site-packages/apscheduler/jobstores/sqlalchemy.py", line 135, in _get_jobs
      jobs.append(self._reconstitute_job(row.job_state))
    File "/Users/wyx/bitcoin_workspace/fibo-strategy/.env/lib/python2.7/site-packages/apscheduler/jobstores/sqlalchemy.py", line 122, in _reconstitute_job
      job.__setstate__(job_state)
    File "/Users/wyx/bitcoin_workspace/fibo-strategy/.env/lib/python2.7/site-packages/apscheduler/job.py", line 260, in __setstate__
      self.func = ref_to_obj(self.func_ref)
    File "/Users/wyx/bitcoin_workspace/fibo-strategy/.env/lib/python2.7/site-packages/apscheduler/util.py", line 277, in ref_to_obj
      raise LookupError('Error resolving reference %s: error looking up object' % ref)
  LookupError: Error resolving reference base.strategy:Strategy.run: error looking up object
  </code></pre>
  
  <p><strong>Supplementary instruction</strong> for Alex Grönholm's question here because it is hard to say in comment</p>
  
  <p>In base/strategy_util.py: </p>
  
  <p><strong>base_strategy</strong> is some classes which <strong>inherit</strong> the BaseStrategy class  in <strong>base/strategy.py</strong> . The BaseStrategy has its <strong>run</strong> method</p>
  
  <pre><code>def _strategy(base_strategy, minute, ticker_table_format):
      class Strategy(base_strategy):
          run_period = minute
  
          def _init_params(self):
              self.ticker_table_format = ticker_table_format
  
      return Strategy()
  
  
  def _create_strategy(base_strategy, minute_list=ALL_MINUTE):
      strategy_list = []
      for minute in minute_list:
          for ticker_table_format in const.TICKER_TABLE_FORMAT.ALL:
              st = _strategy(base_strategy, minute, ticker_table_format)
              strategy_list.append(st)
      return strategy_list
  
  
  def ma_strategy(base_strategy):
      return _create_strategy(base_strategy)
  </code></pre>
  
  <p>In MA/touch_avg.py:</p>
  
  <p><code>MA_TOUCH_AVG</code> <strong>inherit</strong> the BaseStrategy class</p>
  
  <pre><code>from base.strategy import MA_TOUCH_AVG
  from base.strategy_util import ma_strategy
  
  strategy = ma_strategy(MA_TOUCH_AVG)
  </code></pre>
  
  <p>And then I use <code>click</code> to call the strategy like <code>python run_strategy.py run MA touch_avg</code></p>
  
  <p>In run_strategy.py:</p>
  
  <pre><code>@cli.command()
  @click.argument('indicator')
  @click.argument('strategy_name')
  def run(indicator, strategy_name):
      """ run indicator strategy_name """
      real_time_strategy_name = ["touch_avg", "limit"]
      util.script(indicator, strategy_name,
                  real_time=strategy_name in real_time_strategy_name)
  </code></pre>