def get_checksum(content, encoding="utf8", block_size=8192):
    """
    Returns the MD5 checksum in hex for the given content. If 'content'
    is a file-like object, the content will be obtained from its read()
    method. If 'content' is a file path, that file is read and its
    contents used. Otherwise, 'content' is assumed to be the string whose
    checksum is desired. If the content is unicode, it will be encoded
    using the specified encoding.

    To conserve memory, files and file-like objects will be read in blocks,
    with the default block size of 8192 bytes, which is 64 * the digest block
    size of md5 (128). This is optimal for most cases, but you can change this
    by passing in a different value for `block_size`.
    """
    md = hashlib.md5()

    def safe_update(txt):
        if isinstance(txt, six.text_type):
            txt = txt.encode(encoding)
        md.update(txt)

    try:
        isfile = os.path.isfile(content)
    except (TypeError, ValueError):
        # Will happen with binary content.
        isfile = False
    if isfile:
        with open(content, "rb") as ff:
            txt = ff.read(block_size)
            while txt:
                safe_update(txt)
                txt = ff.read(block_size)
    elif hasattr(content, "read"):
        pos = content.tell()
        content.seek(0)
        txt = content.read(block_size)
        while txt:
            safe_update(txt)
            txt = content.read(block_size)
        content.seek(pos)
    else:
        safe_update(content)
    return md.hexdigest()