0

I have the following code:

import zlib


def inflate(infile):
    data = infile.read()
    offset = 0
    while offset < len(data):
        window = data[offset : offset + 2]
        for key, value in zlib_headers.items():
            if window == key:
                decomp_obj = zlib.decompressobj()
                yield key, offset, decomp_obj.decompress(data[offset:])
        if offset == len(data):
            break
        offset += 1


if __name__ == "__main__":
    zlib_headers = {b"\x78\x01": 3, b"\x78\x9c": 6, b"\x78\xda": 9}

    with open("input_file", "rb") as infile:
        *_, last = inflate(infile)

    key, offset, data = last
    start_offset = offset + len(zlib.compress(data, zlib_headers[key]))

    print(start_offset)

Below the function, I'm printing information generated from the iterator. As you can see, I'm doing so for each one, but I only need to do that for the last one. How can I do this? I still need the function to work as a generator using "yield."

4xZnskJp
  • 19
  • 4
  • Does this answer your question? [Cleanest way to get last item from Python iterator](https://stackoverflow.com/questions/2138873/cleanest-way-to-get-last-item-from-python-iterator) – Tzane Apr 22 '22 at 06:08
  • I saw this, but I was a little confused as to what this would look like in my code. I couldn't get it to work. Do you mind showing me what my code what look like doing this? – 4xZnskJp Apr 22 '22 at 06:09
  • What is the__purpose__ of `inflate` function and the multi-case print in main? There could be a simpler solution to evaluate the compression-level based on the [zlib magic headers](https://stackoverflow.com/a/17176881/5730279) (i.e. your `ZLIB_MARKERS`). Can you clarify the use-case and if we can adjust the `inflate` method for a better solution, please. – hc_dev Apr 22 '22 at 08:44
  • The inflate function reads a file at every two bytes and decompresses if one of the headers in ZLIB_MARKERS is read. It's necessary that the header is known for re-compression (it has to use the same compression method). Basically, the reason I asked this question is because I use that function to determine the beginning offset after the final zlib compressed section. This function's usage should still work as a zlib decompresser, though, as I'm also using it for that. I'll update the function as I've optimized it a bit, but feel free to improve on it. – 4xZnskJp Apr 22 '22 at 09:26

1 Answers1

0

Based on, you could do something like this. Different from Cleanest way to get last item from Python iterator, you need to unpack the last item as well, since the yield returns 3 values, which are packed into a tuple, because they are assigned to a single variable last:

def inflate():
    """mock function to yield 3 values"""
    for i in range(10):
        yield i, 10 + i, 20 + i

# With unpacking
*_, last = inflate()
marker_index, offset, data = last
print(marker_index, offset, data)

# With for loop
for last in inflate():
    pass
marker_index, offset, data = last
print(marker_index, offset, data)
Tzane
  • 2,752
  • 1
  • 10
  • 21
  • Alright, thank you. This works perfectly. Just out of curiosity, is there a reason to choose one method over the other? Which would you choose? Is one more efficient than the other? – 4xZnskJp Apr 22 '22 at 06:23
  • @4xZnskJp I can't really say if there is any substantial difference, besides looks, so I would pick the one I think reads easier. If you want to dive more into all the different ways this can be done and their pros and cons, I suggest you check out the linked thread. – Tzane Apr 22 '22 at 06:42