title: Interact with background task with commands in submodule [discord.py]
body: <p>I have a Discord bot written with the <em>non-rewrite</em> version of discord.py that sends a heartbeat-like message (among other things). I don't know if I understood it correctly but from tests, I found out that I need to have the <code>async def heartbeat()</code> function in the <code>main.py</code> file.</p>
  
  <p>Excerpt from <code>main.py</code> (heartbeat works as intended):</p>
  
  <pre><code>[...]
  import asyncio
  import datetime
  from configparser import ConfigParser
  
  startup_time = datetime.datetime.utcnow()
  [...]
  
  async def heartbeat():
      await bot.wait_until_ready()
  
      heartbeat_config = ConfigParser()
      heartbeat_config.read('./config/config.ini')
      hb_freq = int(heartbeat_config.get('Heartbeat', 'hb_freq'))  # frequency of heartbeat message
      hb_channel = heartbeat_config.get('Heartbeat', 'hb_channel')  # target channel of heartbeat message
      hb_channel = bot.get_channel(hb_channel)  # get channel from bot's channels
  
      await bot.send_message(hb_channel, "Starting up at: `" + str(startup_time) + "`")
      await asyncio.sleep(hb_freq)  # sleep for hb_freq seconds before entering loop
      while not bot.is_closed:
          now = datetime.datetime.utcnow()  # time right now
          tdelta = now - startup_time  # time since startup
          tdelta = tdelta - datetime.timedelta(microseconds=tdelta.microseconds)  # remove microseconds from tdelta
          beat = await bot.send_message(hb_channel, "Still running\nSince: `" + str(startup_time) + "`.\nCurrent uptime: `" + str(tdelta))
          await asyncio.sleep(hb_freq)  # sleep for hb_freq seconds before initialising next beat
          await bot.delete_message(beat)  # delete old beat so it can be replaced
  
  [...]
  if __name__ == "__main__":
      global heartbeat_task
      heartbeat_task = bot.loop.create_task(heartbeat())  # creates heartbeat task in the background
      bot.run(token)  # run bot
  </code></pre>
  
  <p>I have some commands that are supposed to interact with the created <code>heartbeat_task</code>, but they are in a different module, called <code>dev.py</code> (residing in the same directory as <code>main.py</code>).</p>
  
  <p>Excerpt from <code>dev.py</code>:</p>
  
  <pre><code>[...]
  from main import heartbeat_task, heartbeat
  [...]
  @commands.group(pass_context=True)
  async def heart(self, ctx):
      if ctx.invoked_subcommand is None:
          return
  
  @heart.command(pass_context=True)
  async def stop(self, ctx):
      # should cancel the task from main.py
      heartbeat_task.cancel()
      await self.bot.say('Heartbeat stopped by user {}'.format(ctx.message.author.name))
  
  @heart.command(pass_context=True)
  async def start(self, ctx):
      # start the heartbeat if it is not running
      global heartbeat_task
      if heartbeat_task.cancelled():
          heartbeat_task = self.bot.loop.create_task(heartbeat())
          await self.bot.say('Heartbeat started by user {}'.format(ctx.message.author.name))
      else:
          return
  [...]
  </code></pre>
  
  <p>These commands work perfectly fine when they are part of <code>main.py</code> (with the necessary adjustments of course, like removing <code>self</code>, the import, etc), but since I want all developer related commands to go into a module of their own, so I tried moving them.</p>
  
  <p>I get the following error when I try to load the module:</p>
  
  <p><code>ImportError: cannot import name 'heartbeat_task'.</code></p>
  
  <p>Removing that import from <code>dev.py</code> leads to a successful loading of the module, but upon using either of the commands, the console throws an error:</p>
  
  <p><code>NameError: name 'heartbeat_task' is not defined</code></p>
  
  <p>Which traces back to the line <code>heartbeat_task.cancel()</code> (in the case of <code>heart stop</code> // <code>if heartbeat_task.cancelled():</code> (in the case of <code>heart start</code>).</p>
  
  <p>Now my question.
  How can I have the async <code>heartbeat()</code> in <code>main.py</code> but influence the task with the commands in the <code>dev.py</code> module?</p>
  
  <p>And if I can't, what are feasible alternatives that keep the commands in <code>dev.py</code> (the function itself doesn't need to stay in <code>main.py</code> but is preferred to stay there)?</p>
  
  <p>(I have searched for quite some time and couldn't find a problem like mine or a solution that happened to work for me too)</p>