<SYSTEM_TASK:>
Solve the following problem using Python, implementing the functions described below, one line at a time
<END_TASK>
<USER_TASK:>
Description:
 async def download_file(context, url, abs_filename, session=None, chunk_size=128):
 """Download a file, async. Args: context (scriptworker.context.Context):
 the scriptworker context. url (str):
 the url to download abs_filename (str):
 the path to download to session (aiohttp.ClientSession, optional):
 the session to use. If None, use context.session. Defaults to None. chunk_size (int, optional):
 the chunk size to read from the response at a time. Default is 128. """

    session = session or context.session
    loggable_url = get_loggable_url(url)
    log.info("Downloading %s", loggable_url)
    parent_dir = os.path.dirname(abs_filename)
    async with session.get(url) as resp:
        if resp.status == 404:
            await _log_download_error(resp, "404 downloading %(url)s: %(status)s; body=%(body)s")
            raise Download404("{} status {}!".format(loggable_url, resp.status))
        elif resp.status != 200:
            await _log_download_error(resp, "Failed to download %(url)s: %(status)s; body=%(body)s")
            raise DownloadError("{} status {} is not 200!".format(loggable_url, resp.status))
        makedirs(parent_dir)
        with open(abs_filename, "wb") as fd:
            while True:
                chunk = await resp.content.read(chunk_size)
                if not chunk:
                    break
                fd.write(chunk)
    log.info("Done")