docstr: Create a new instance of KnapsackJobScheduler.
docstr_tok: ["Create","a","new","instance","of","KnapsackJobScheduler","."]
code: def __init__(self, workflow, executor_plugin: ExecutorPlugin):
      """Create a new instance of KnapsackJobScheduler."""
      self.workflow = workflow
  
      self.dryrun = self.workflow.dryrun
      self.touch = self.workflow.touch
      self.quiet = self.workflow.output_settings.quiet
      self.keepgoing = self.workflow.execution_settings.keep_going
      self.running = set()
      self.failed = set()
      self.finished_jobs = 0
      self.greediness = self.workflow.scheduling_settings.greediness
      self.max_jobs_per_second = (
          self.workflow.scheduling_settings.max_jobs_per_second
      )
      self._tofinish = []
      self._toerror = []
      self.handle_job_success = True
      self.update_resources = True
      self.print_progress = not self.quiet and not self.dryrun
      self.update_checkpoint_dependencies = not self.dryrun
  
      nodes_unset = workflow.global_resources["_nodes"] is None
  
      self.global_resources = {
          name: (sys.maxsize if res is None else res)
          for name, res in workflow.global_resources.items()
      }
  
      if not nodes_unset:
          # Do not restrict cores locally if nodes are used (i.e. in case of cluster/cloud submission).
          self.global_resources["_cores"] = sys.maxsize
  
      self.resources = dict(self.global_resources)
  
      self._open_jobs = threading.Semaphore(0)
      self._lock = threading.Lock()
  
      self._errors = False
      self._executor_error = None
      self._finished = False
      self._job_queue = None
      self._last_job_selection_empty = False
      self.submit_callback = self._noop
      self.finish_callback = self._proceed
  
      if workflow.remote_execution_settings.immediate_submit:
          self.submit_callback = self._proceed
          self.finish_callback = self._noop
  
      self._local_executor = None
  
      if self.workflow.local_exec:
          self._executor = executor_plugin.executor(
              self.workflow,
              logger,
          )
      else:
          self._executor = executor_plugin.executor(
              self.workflow,
              logger,
          )
          self._local_executor = (
              ExecutorPluginRegistry()
              .get_plugin("local")
              .executor(
                  self.workflow,
                  logger,
              )
          )
  
      from throttler import Throttler
  
      if not self.dryrun:
          max_jobs_frac = Fraction(
              self.max_jobs_per_second
          ).limit_denominator()
          self.rate_limiter = Throttler(
              rate_limit=max_jobs_frac.numerator,
              period=max_jobs_frac.denominator,
          )
      else:
          # essentially no rate limit
          self.rate_limiter = DummyRateLimiter()
  
      # Choose job selector (greedy or ILP)
      self.job_selector = self.job_selector_greedy
      if self.workflow.scheduling_settings.scheduler == "ilp":
          import pulp
  
          if pulp.apis.LpSolverDefault is None:
              logger.warning(
                  "Falling back to greedy scheduler because no default "
                  "solver is found for pulp (you have to install either "
                  "coincbc or glpk)."
              )
          else:
              self.job_selector = self.job_selector_ilp
  
      self._user_kill = None
      try:
          signal.signal(signal.SIGTERM, self.exit_gracefully)
      except ValueError:
          # If this fails, it is due to scheduler not being invoked in the main thread.
          # This can only happen with --gui, in which case it is fine for now.
          pass
      self._open_jobs.release()
  
imports: import asyncio
  from collections import defaultdict
  import math
  import os, signal, sys
  import threading
  from functools import partial
  from itertools import chain, accumulate
  from contextlib import ContextDecorator
  from snakemake_interface_executor_plugins.scheduler import JobSchedulerExecutorInterface
  from snakemake_interface_executor_plugins.registry import ExecutorPluginRegistry
  from snakemake_interface_executor_plugins.registry import Plugin
  from snakemake_interface_executor_plugins.settings import ExecMode
  from snakemake.common import async_run
  from snakemake.exceptions import RuleException, WorkflowError, print_exception
  from snakemake.logging import logger
  from fractions import Fraction
label_desc: Use image node_id 1 to create a new JobScheduler object from inherited base classes: JobSchedulerExecutorInterface with example: obj = JobScheduler(workflow, executor_plugin)