How to convert an iterable to a stream?












11















If I've got an iterable containing strings, is there a simple way to turn it into a stream? I want to do something like this:



def make_file():
yield "hellon"
yield "worldn"

output = tarfile.TarFile(…)
stream = iterable_to_stream(make_file())
output.addfile(…, stream)









share|improve this question

























  • I don't know streams well, but do you want stream = io.StringIO("".join(make_file())) ?

    – utdemir
    Jul 11 '11 at 23:25








  • 2





    Nope — I don't want that. make_file() may return a large file, and I'd rather not load it into memory.

    – David Wolever
    Jul 11 '11 at 23:41











  • interesting link: hg.python.org/cpython/file/ab162f925761/Lib/tarfile.py#l249

    – SingleNegationElimination
    Jul 12 '11 at 4:02











  • @TokenMacGuy: Sorry, I don't think I see the significance of that link…

    – David Wolever
    Jul 12 '11 at 4:04
















11















If I've got an iterable containing strings, is there a simple way to turn it into a stream? I want to do something like this:



def make_file():
yield "hellon"
yield "worldn"

output = tarfile.TarFile(…)
stream = iterable_to_stream(make_file())
output.addfile(…, stream)









share|improve this question

























  • I don't know streams well, but do you want stream = io.StringIO("".join(make_file())) ?

    – utdemir
    Jul 11 '11 at 23:25








  • 2





    Nope — I don't want that. make_file() may return a large file, and I'd rather not load it into memory.

    – David Wolever
    Jul 11 '11 at 23:41











  • interesting link: hg.python.org/cpython/file/ab162f925761/Lib/tarfile.py#l249

    – SingleNegationElimination
    Jul 12 '11 at 4:02











  • @TokenMacGuy: Sorry, I don't think I see the significance of that link…

    – David Wolever
    Jul 12 '11 at 4:04














11












11








11


6






If I've got an iterable containing strings, is there a simple way to turn it into a stream? I want to do something like this:



def make_file():
yield "hellon"
yield "worldn"

output = tarfile.TarFile(…)
stream = iterable_to_stream(make_file())
output.addfile(…, stream)









share|improve this question
















If I've got an iterable containing strings, is there a simple way to turn it into a stream? I want to do something like this:



def make_file():
yield "hellon"
yield "worldn"

output = tarfile.TarFile(…)
stream = iterable_to_stream(make_file())
output.addfile(…, stream)






python stream iterator






share|improve this question















share|improve this question













share|improve this question




share|improve this question








edited Nov 24 '18 at 20:58









martineau

68.6k1090183




68.6k1090183










asked Jul 11 '11 at 23:18









David WoleverDavid Wolever

76.5k60264424




76.5k60264424













  • I don't know streams well, but do you want stream = io.StringIO("".join(make_file())) ?

    – utdemir
    Jul 11 '11 at 23:25








  • 2





    Nope — I don't want that. make_file() may return a large file, and I'd rather not load it into memory.

    – David Wolever
    Jul 11 '11 at 23:41











  • interesting link: hg.python.org/cpython/file/ab162f925761/Lib/tarfile.py#l249

    – SingleNegationElimination
    Jul 12 '11 at 4:02











  • @TokenMacGuy: Sorry, I don't think I see the significance of that link…

    – David Wolever
    Jul 12 '11 at 4:04



















  • I don't know streams well, but do you want stream = io.StringIO("".join(make_file())) ?

    – utdemir
    Jul 11 '11 at 23:25








  • 2





    Nope — I don't want that. make_file() may return a large file, and I'd rather not load it into memory.

    – David Wolever
    Jul 11 '11 at 23:41











  • interesting link: hg.python.org/cpython/file/ab162f925761/Lib/tarfile.py#l249

    – SingleNegationElimination
    Jul 12 '11 at 4:02











  • @TokenMacGuy: Sorry, I don't think I see the significance of that link…

    – David Wolever
    Jul 12 '11 at 4:04

















I don't know streams well, but do you want stream = io.StringIO("".join(make_file())) ?

– utdemir
Jul 11 '11 at 23:25







I don't know streams well, but do you want stream = io.StringIO("".join(make_file())) ?

– utdemir
Jul 11 '11 at 23:25






2




2





Nope — I don't want that. make_file() may return a large file, and I'd rather not load it into memory.

– David Wolever
Jul 11 '11 at 23:41





Nope — I don't want that. make_file() may return a large file, and I'd rather not load it into memory.

– David Wolever
Jul 11 '11 at 23:41













interesting link: hg.python.org/cpython/file/ab162f925761/Lib/tarfile.py#l249

– SingleNegationElimination
Jul 12 '11 at 4:02





interesting link: hg.python.org/cpython/file/ab162f925761/Lib/tarfile.py#l249

– SingleNegationElimination
Jul 12 '11 at 4:02













@TokenMacGuy: Sorry, I don't think I see the significance of that link…

– David Wolever
Jul 12 '11 at 4:04





@TokenMacGuy: Sorry, I don't think I see the significance of that link…

– David Wolever
Jul 12 '11 at 4:04












5 Answers
5






active

oldest

votes


















12














Here's my streaming iterator an experimental branch of urllib3 supporting streaming chunked request via iterables:



class IterStreamer(object):
"""
File-like streaming iterator.
"""
def __init__(self, generator):
self.generator = generator
self.iterator = iter(generator)
self.leftover = ''

def __len__(self):
return self.generator.__len__()

def __iter__(self):
return self.iterator

def next(self):
return self.iterator.next()

def read(self, size):
data = self.leftover
count = len(self.leftover)

if count < size:
try:
while count < size:
chunk = self.next()
data += chunk
count += len(chunk)
except StopIteration:
pass

self.leftover = data[size:]

return data[:size]


Source with context:
https://github.com/shazow/urllib3/blob/filepost-stream/urllib3/filepost.py#L23



Related unit tests:
https://github.com/shazow/urllib3/blob/filepost-stream/test/test_filepost.py#L9



Alas this code hasn't made it into the stable branch yet as sizeless chunked requests are poorly supported, but it should be a good foundation for what you're trying to do. See the source link for examples showing how it can be used.






share|improve this answer





















  • 1





    This has a bug where it will continue to emit the last leftover bit of data forever.

    – Nick Retallack
    May 2 '12 at 20:33






  • 1





    Swap out the pass for return data and the bug is gone.

    – pi.
    Sep 24 '12 at 9:33






  • 1





    No. Swap out the pass for self.leftover = ''; return data and the bug is gone.

    – Honza Javorek
    May 2 '13 at 14:33











  • Fixed the bug you guys mentioned. Sorry for the lack of response, didn't notice Stackoverflow's notifications for a long time. :)

    – shazow
    May 2 '13 at 17:54











  • Hyperlinks are broken.

    – Mechanical snail
    Nov 28 '13 at 6:37



















23














Python 3 has a new I/O stream API (library docs), replacing the old file-like object protocol. (The new API is also available in Python 2 in the io module, and it's backwards-compatible with the file-like object protocol.)



Here's an implementation for the new API, in Python 2 and 3:



import io

def iterable_to_stream(iterable, buffer_size=io.DEFAULT_BUFFER_SIZE):
"""
Lets you use an iterable (e.g. a generator) that yields bytestrings as a read-only
input stream.

The stream implements Python 3's newer I/O API (available in Python 2's io module).
For efficiency, the stream is buffered.
"""
class IterStream(io.RawIOBase):
def __init__(self):
self.leftover = None
def readable(self):
return True
def readinto(self, b):
try:
l = len(b) # We're supposed to return at most this much
chunk = self.leftover or next(iterable)
output, self.leftover = chunk[:l], chunk[l:]
b[:len(output)] = output
return len(output)
except StopIteration:
return 0 # indicate EOF
return io.BufferedReader(IterStream(), buffer_size=buffer_size)


Example usage:



with iterable_to_stream(str(x**2).encode('utf8') for x in range(11)) as s:
print(s.read())





share|improve this answer































    10














    Since it doesn't look like there is a "standard" way of doing it, I've banged together a simple implementation:



    class iter_to_stream(object):
    def __init__(self, iterable):
    self.buffered = ""
    self.iter = iter(iterable)

    def read(self, size):
    result = ""
    while size > 0:
    data = self.buffered or next(self.iter, None)
    self.buffered = ""
    if data is None:
    break
    size -= len(data)
    if size < 0:
    data, self.buffered = data[:size], data[size:]
    result += data
    return result





    share|improve this answer


























    • +1 Nicely done!

      – Sean Vieira
      Jul 12 '11 at 0:19



















    4














    A starting point:



    class iterable_to_stream:
    def __init__(self, iterable):
    self.iter = iter(iterable)

    def read(self):
    try:
    return self.iter.next()
    except StopIteration:
    return ""





    share|improve this answer
























    • Hhmm… While that would most certainly explode on its own (what if next(iter) returns ""? What if someone has the audacity to pass a size into read(…))… I guess I could use a BufferedReader to take care of those details…

      – David Wolever
      Jul 11 '11 at 23:40











    • Sorry dude, this appears to be unworkable. BufferedReader needs an instance of RawIOBase, and this doesn't come anywhere near to implementing that interface… And it doesn't even implement the basic stream API (eg, read() doesn't accept a size).

      – David Wolever
      Jul 11 '11 at 23:57











    • @David Wolever: Seems like coding a RawIOBase-like wrapper for your iterable and passing that to BufferReader would be feasible. RawIOBase objects only have 4 methods and you might be able to get away with only implementing the 3 read...() ones.

      – martineau
      Jul 12 '11 at 0:33





















    0














    TarFile takes anything that provides a file-like interface -- so you could either use StringIO (io.StringIO if you are using Python 3.X) to yield what you need to TarFile.addfile() or you could create your own class that provides a file-like interface and yields what you need.






    share|improve this answer
























    • Right — but is there any way to stream an iterator through a StringIO? I'd rather not load the entire input file into memory before writing it to the StringIO.

      – David Wolever
      Jul 11 '11 at 23:38













    • @David -- not that I know of. I'd give you an example of wrapping a class around StringIO, but it looks like you've got what you need already :-)

      – Sean Vieira
      Jul 12 '11 at 0:18











    Your Answer






    StackExchange.ifUsing("editor", function () {
    StackExchange.using("externalEditor", function () {
    StackExchange.using("snippets", function () {
    StackExchange.snippets.init();
    });
    });
    }, "code-snippets");

    StackExchange.ready(function() {
    var channelOptions = {
    tags: "".split(" "),
    id: "1"
    };
    initTagRenderer("".split(" "), "".split(" "), channelOptions);

    StackExchange.using("externalEditor", function() {
    // Have to fire editor after snippets, if snippets enabled
    if (StackExchange.settings.snippets.snippetsEnabled) {
    StackExchange.using("snippets", function() {
    createEditor();
    });
    }
    else {
    createEditor();
    }
    });

    function createEditor() {
    StackExchange.prepareEditor({
    heartbeatType: 'answer',
    autoActivateHeartbeat: false,
    convertImagesToLinks: true,
    noModals: true,
    showLowRepImageUploadWarning: true,
    reputationToPostImages: 10,
    bindNavPrevention: true,
    postfix: "",
    imageUploader: {
    brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
    contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
    allowUrls: true
    },
    onDemand: true,
    discardSelector: ".discard-answer"
    ,immediatelyShowMarkdownHelp:true
    });


    }
    });














    draft saved

    draft discarded


















    StackExchange.ready(
    function () {
    StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f6657820%2fhow-to-convert-an-iterable-to-a-stream%23new-answer', 'question_page');
    }
    );

    Post as a guest















    Required, but never shown

























    5 Answers
    5






    active

    oldest

    votes








    5 Answers
    5






    active

    oldest

    votes









    active

    oldest

    votes






    active

    oldest

    votes









    12














    Here's my streaming iterator an experimental branch of urllib3 supporting streaming chunked request via iterables:



    class IterStreamer(object):
    """
    File-like streaming iterator.
    """
    def __init__(self, generator):
    self.generator = generator
    self.iterator = iter(generator)
    self.leftover = ''

    def __len__(self):
    return self.generator.__len__()

    def __iter__(self):
    return self.iterator

    def next(self):
    return self.iterator.next()

    def read(self, size):
    data = self.leftover
    count = len(self.leftover)

    if count < size:
    try:
    while count < size:
    chunk = self.next()
    data += chunk
    count += len(chunk)
    except StopIteration:
    pass

    self.leftover = data[size:]

    return data[:size]


    Source with context:
    https://github.com/shazow/urllib3/blob/filepost-stream/urllib3/filepost.py#L23



    Related unit tests:
    https://github.com/shazow/urllib3/blob/filepost-stream/test/test_filepost.py#L9



    Alas this code hasn't made it into the stable branch yet as sizeless chunked requests are poorly supported, but it should be a good foundation for what you're trying to do. See the source link for examples showing how it can be used.






    share|improve this answer





















    • 1





      This has a bug where it will continue to emit the last leftover bit of data forever.

      – Nick Retallack
      May 2 '12 at 20:33






    • 1





      Swap out the pass for return data and the bug is gone.

      – pi.
      Sep 24 '12 at 9:33






    • 1





      No. Swap out the pass for self.leftover = ''; return data and the bug is gone.

      – Honza Javorek
      May 2 '13 at 14:33











    • Fixed the bug you guys mentioned. Sorry for the lack of response, didn't notice Stackoverflow's notifications for a long time. :)

      – shazow
      May 2 '13 at 17:54











    • Hyperlinks are broken.

      – Mechanical snail
      Nov 28 '13 at 6:37
















    12














    Here's my streaming iterator an experimental branch of urllib3 supporting streaming chunked request via iterables:



    class IterStreamer(object):
    """
    File-like streaming iterator.
    """
    def __init__(self, generator):
    self.generator = generator
    self.iterator = iter(generator)
    self.leftover = ''

    def __len__(self):
    return self.generator.__len__()

    def __iter__(self):
    return self.iterator

    def next(self):
    return self.iterator.next()

    def read(self, size):
    data = self.leftover
    count = len(self.leftover)

    if count < size:
    try:
    while count < size:
    chunk = self.next()
    data += chunk
    count += len(chunk)
    except StopIteration:
    pass

    self.leftover = data[size:]

    return data[:size]


    Source with context:
    https://github.com/shazow/urllib3/blob/filepost-stream/urllib3/filepost.py#L23



    Related unit tests:
    https://github.com/shazow/urllib3/blob/filepost-stream/test/test_filepost.py#L9



    Alas this code hasn't made it into the stable branch yet as sizeless chunked requests are poorly supported, but it should be a good foundation for what you're trying to do. See the source link for examples showing how it can be used.






    share|improve this answer





















    • 1





      This has a bug where it will continue to emit the last leftover bit of data forever.

      – Nick Retallack
      May 2 '12 at 20:33






    • 1





      Swap out the pass for return data and the bug is gone.

      – pi.
      Sep 24 '12 at 9:33






    • 1





      No. Swap out the pass for self.leftover = ''; return data and the bug is gone.

      – Honza Javorek
      May 2 '13 at 14:33











    • Fixed the bug you guys mentioned. Sorry for the lack of response, didn't notice Stackoverflow's notifications for a long time. :)

      – shazow
      May 2 '13 at 17:54











    • Hyperlinks are broken.

      – Mechanical snail
      Nov 28 '13 at 6:37














    12












    12








    12







    Here's my streaming iterator an experimental branch of urllib3 supporting streaming chunked request via iterables:



    class IterStreamer(object):
    """
    File-like streaming iterator.
    """
    def __init__(self, generator):
    self.generator = generator
    self.iterator = iter(generator)
    self.leftover = ''

    def __len__(self):
    return self.generator.__len__()

    def __iter__(self):
    return self.iterator

    def next(self):
    return self.iterator.next()

    def read(self, size):
    data = self.leftover
    count = len(self.leftover)

    if count < size:
    try:
    while count < size:
    chunk = self.next()
    data += chunk
    count += len(chunk)
    except StopIteration:
    pass

    self.leftover = data[size:]

    return data[:size]


    Source with context:
    https://github.com/shazow/urllib3/blob/filepost-stream/urllib3/filepost.py#L23



    Related unit tests:
    https://github.com/shazow/urllib3/blob/filepost-stream/test/test_filepost.py#L9



    Alas this code hasn't made it into the stable branch yet as sizeless chunked requests are poorly supported, but it should be a good foundation for what you're trying to do. See the source link for examples showing how it can be used.






    share|improve this answer















    Here's my streaming iterator an experimental branch of urllib3 supporting streaming chunked request via iterables:



    class IterStreamer(object):
    """
    File-like streaming iterator.
    """
    def __init__(self, generator):
    self.generator = generator
    self.iterator = iter(generator)
    self.leftover = ''

    def __len__(self):
    return self.generator.__len__()

    def __iter__(self):
    return self.iterator

    def next(self):
    return self.iterator.next()

    def read(self, size):
    data = self.leftover
    count = len(self.leftover)

    if count < size:
    try:
    while count < size:
    chunk = self.next()
    data += chunk
    count += len(chunk)
    except StopIteration:
    pass

    self.leftover = data[size:]

    return data[:size]


    Source with context:
    https://github.com/shazow/urllib3/blob/filepost-stream/urllib3/filepost.py#L23



    Related unit tests:
    https://github.com/shazow/urllib3/blob/filepost-stream/test/test_filepost.py#L9



    Alas this code hasn't made it into the stable branch yet as sizeless chunked requests are poorly supported, but it should be a good foundation for what you're trying to do. See the source link for examples showing how it can be used.







    share|improve this answer














    share|improve this answer



    share|improve this answer








    edited Aug 24 '16 at 22:30









    James Wheare

    3,65911922




    3,65911922










    answered Jul 12 '11 at 2:40









    shazowshazow

    8,47711726




    8,47711726








    • 1





      This has a bug where it will continue to emit the last leftover bit of data forever.

      – Nick Retallack
      May 2 '12 at 20:33






    • 1





      Swap out the pass for return data and the bug is gone.

      – pi.
      Sep 24 '12 at 9:33






    • 1





      No. Swap out the pass for self.leftover = ''; return data and the bug is gone.

      – Honza Javorek
      May 2 '13 at 14:33











    • Fixed the bug you guys mentioned. Sorry for the lack of response, didn't notice Stackoverflow's notifications for a long time. :)

      – shazow
      May 2 '13 at 17:54











    • Hyperlinks are broken.

      – Mechanical snail
      Nov 28 '13 at 6:37














    • 1





      This has a bug where it will continue to emit the last leftover bit of data forever.

      – Nick Retallack
      May 2 '12 at 20:33






    • 1





      Swap out the pass for return data and the bug is gone.

      – pi.
      Sep 24 '12 at 9:33






    • 1





      No. Swap out the pass for self.leftover = ''; return data and the bug is gone.

      – Honza Javorek
      May 2 '13 at 14:33











    • Fixed the bug you guys mentioned. Sorry for the lack of response, didn't notice Stackoverflow's notifications for a long time. :)

      – shazow
      May 2 '13 at 17:54











    • Hyperlinks are broken.

      – Mechanical snail
      Nov 28 '13 at 6:37








    1




    1





    This has a bug where it will continue to emit the last leftover bit of data forever.

    – Nick Retallack
    May 2 '12 at 20:33





    This has a bug where it will continue to emit the last leftover bit of data forever.

    – Nick Retallack
    May 2 '12 at 20:33




    1




    1





    Swap out the pass for return data and the bug is gone.

    – pi.
    Sep 24 '12 at 9:33





    Swap out the pass for return data and the bug is gone.

    – pi.
    Sep 24 '12 at 9:33




    1




    1





    No. Swap out the pass for self.leftover = ''; return data and the bug is gone.

    – Honza Javorek
    May 2 '13 at 14:33





    No. Swap out the pass for self.leftover = ''; return data and the bug is gone.

    – Honza Javorek
    May 2 '13 at 14:33













    Fixed the bug you guys mentioned. Sorry for the lack of response, didn't notice Stackoverflow's notifications for a long time. :)

    – shazow
    May 2 '13 at 17:54





    Fixed the bug you guys mentioned. Sorry for the lack of response, didn't notice Stackoverflow's notifications for a long time. :)

    – shazow
    May 2 '13 at 17:54













    Hyperlinks are broken.

    – Mechanical snail
    Nov 28 '13 at 6:37





    Hyperlinks are broken.

    – Mechanical snail
    Nov 28 '13 at 6:37













    23














    Python 3 has a new I/O stream API (library docs), replacing the old file-like object protocol. (The new API is also available in Python 2 in the io module, and it's backwards-compatible with the file-like object protocol.)



    Here's an implementation for the new API, in Python 2 and 3:



    import io

    def iterable_to_stream(iterable, buffer_size=io.DEFAULT_BUFFER_SIZE):
    """
    Lets you use an iterable (e.g. a generator) that yields bytestrings as a read-only
    input stream.

    The stream implements Python 3's newer I/O API (available in Python 2's io module).
    For efficiency, the stream is buffered.
    """
    class IterStream(io.RawIOBase):
    def __init__(self):
    self.leftover = None
    def readable(self):
    return True
    def readinto(self, b):
    try:
    l = len(b) # We're supposed to return at most this much
    chunk = self.leftover or next(iterable)
    output, self.leftover = chunk[:l], chunk[l:]
    b[:len(output)] = output
    return len(output)
    except StopIteration:
    return 0 # indicate EOF
    return io.BufferedReader(IterStream(), buffer_size=buffer_size)


    Example usage:



    with iterable_to_stream(str(x**2).encode('utf8') for x in range(11)) as s:
    print(s.read())





    share|improve this answer




























      23














      Python 3 has a new I/O stream API (library docs), replacing the old file-like object protocol. (The new API is also available in Python 2 in the io module, and it's backwards-compatible with the file-like object protocol.)



      Here's an implementation for the new API, in Python 2 and 3:



      import io

      def iterable_to_stream(iterable, buffer_size=io.DEFAULT_BUFFER_SIZE):
      """
      Lets you use an iterable (e.g. a generator) that yields bytestrings as a read-only
      input stream.

      The stream implements Python 3's newer I/O API (available in Python 2's io module).
      For efficiency, the stream is buffered.
      """
      class IterStream(io.RawIOBase):
      def __init__(self):
      self.leftover = None
      def readable(self):
      return True
      def readinto(self, b):
      try:
      l = len(b) # We're supposed to return at most this much
      chunk = self.leftover or next(iterable)
      output, self.leftover = chunk[:l], chunk[l:]
      b[:len(output)] = output
      return len(output)
      except StopIteration:
      return 0 # indicate EOF
      return io.BufferedReader(IterStream(), buffer_size=buffer_size)


      Example usage:



      with iterable_to_stream(str(x**2).encode('utf8') for x in range(11)) as s:
      print(s.read())





      share|improve this answer


























        23












        23








        23







        Python 3 has a new I/O stream API (library docs), replacing the old file-like object protocol. (The new API is also available in Python 2 in the io module, and it's backwards-compatible with the file-like object protocol.)



        Here's an implementation for the new API, in Python 2 and 3:



        import io

        def iterable_to_stream(iterable, buffer_size=io.DEFAULT_BUFFER_SIZE):
        """
        Lets you use an iterable (e.g. a generator) that yields bytestrings as a read-only
        input stream.

        The stream implements Python 3's newer I/O API (available in Python 2's io module).
        For efficiency, the stream is buffered.
        """
        class IterStream(io.RawIOBase):
        def __init__(self):
        self.leftover = None
        def readable(self):
        return True
        def readinto(self, b):
        try:
        l = len(b) # We're supposed to return at most this much
        chunk = self.leftover or next(iterable)
        output, self.leftover = chunk[:l], chunk[l:]
        b[:len(output)] = output
        return len(output)
        except StopIteration:
        return 0 # indicate EOF
        return io.BufferedReader(IterStream(), buffer_size=buffer_size)


        Example usage:



        with iterable_to_stream(str(x**2).encode('utf8') for x in range(11)) as s:
        print(s.read())





        share|improve this answer













        Python 3 has a new I/O stream API (library docs), replacing the old file-like object protocol. (The new API is also available in Python 2 in the io module, and it's backwards-compatible with the file-like object protocol.)



        Here's an implementation for the new API, in Python 2 and 3:



        import io

        def iterable_to_stream(iterable, buffer_size=io.DEFAULT_BUFFER_SIZE):
        """
        Lets you use an iterable (e.g. a generator) that yields bytestrings as a read-only
        input stream.

        The stream implements Python 3's newer I/O API (available in Python 2's io module).
        For efficiency, the stream is buffered.
        """
        class IterStream(io.RawIOBase):
        def __init__(self):
        self.leftover = None
        def readable(self):
        return True
        def readinto(self, b):
        try:
        l = len(b) # We're supposed to return at most this much
        chunk = self.leftover or next(iterable)
        output, self.leftover = chunk[:l], chunk[l:]
        b[:len(output)] = output
        return len(output)
        except StopIteration:
        return 0 # indicate EOF
        return io.BufferedReader(IterStream(), buffer_size=buffer_size)


        Example usage:



        with iterable_to_stream(str(x**2).encode('utf8') for x in range(11)) as s:
        print(s.read())






        share|improve this answer












        share|improve this answer



        share|improve this answer










        answered Nov 28 '13 at 7:22









        Mechanical snailMechanical snail

        19.6k107298




        19.6k107298























            10














            Since it doesn't look like there is a "standard" way of doing it, I've banged together a simple implementation:



            class iter_to_stream(object):
            def __init__(self, iterable):
            self.buffered = ""
            self.iter = iter(iterable)

            def read(self, size):
            result = ""
            while size > 0:
            data = self.buffered or next(self.iter, None)
            self.buffered = ""
            if data is None:
            break
            size -= len(data)
            if size < 0:
            data, self.buffered = data[:size], data[size:]
            result += data
            return result





            share|improve this answer


























            • +1 Nicely done!

              – Sean Vieira
              Jul 12 '11 at 0:19
















            10














            Since it doesn't look like there is a "standard" way of doing it, I've banged together a simple implementation:



            class iter_to_stream(object):
            def __init__(self, iterable):
            self.buffered = ""
            self.iter = iter(iterable)

            def read(self, size):
            result = ""
            while size > 0:
            data = self.buffered or next(self.iter, None)
            self.buffered = ""
            if data is None:
            break
            size -= len(data)
            if size < 0:
            data, self.buffered = data[:size], data[size:]
            result += data
            return result





            share|improve this answer


























            • +1 Nicely done!

              – Sean Vieira
              Jul 12 '11 at 0:19














            10












            10








            10







            Since it doesn't look like there is a "standard" way of doing it, I've banged together a simple implementation:



            class iter_to_stream(object):
            def __init__(self, iterable):
            self.buffered = ""
            self.iter = iter(iterable)

            def read(self, size):
            result = ""
            while size > 0:
            data = self.buffered or next(self.iter, None)
            self.buffered = ""
            if data is None:
            break
            size -= len(data)
            if size < 0:
            data, self.buffered = data[:size], data[size:]
            result += data
            return result





            share|improve this answer















            Since it doesn't look like there is a "standard" way of doing it, I've banged together a simple implementation:



            class iter_to_stream(object):
            def __init__(self, iterable):
            self.buffered = ""
            self.iter = iter(iterable)

            def read(self, size):
            result = ""
            while size > 0:
            data = self.buffered or next(self.iter, None)
            self.buffered = ""
            if data is None:
            break
            size -= len(data)
            if size < 0:
            data, self.buffered = data[:size], data[size:]
            result += data
            return result






            share|improve this answer














            share|improve this answer



            share|improve this answer








            edited Nov 15 '12 at 16:05

























            answered Jul 12 '11 at 0:01









            David WoleverDavid Wolever

            76.5k60264424




            76.5k60264424













            • +1 Nicely done!

              – Sean Vieira
              Jul 12 '11 at 0:19



















            • +1 Nicely done!

              – Sean Vieira
              Jul 12 '11 at 0:19

















            +1 Nicely done!

            – Sean Vieira
            Jul 12 '11 at 0:19





            +1 Nicely done!

            – Sean Vieira
            Jul 12 '11 at 0:19











            4














            A starting point:



            class iterable_to_stream:
            def __init__(self, iterable):
            self.iter = iter(iterable)

            def read(self):
            try:
            return self.iter.next()
            except StopIteration:
            return ""





            share|improve this answer
























            • Hhmm… While that would most certainly explode on its own (what if next(iter) returns ""? What if someone has the audacity to pass a size into read(…))… I guess I could use a BufferedReader to take care of those details…

              – David Wolever
              Jul 11 '11 at 23:40











            • Sorry dude, this appears to be unworkable. BufferedReader needs an instance of RawIOBase, and this doesn't come anywhere near to implementing that interface… And it doesn't even implement the basic stream API (eg, read() doesn't accept a size).

              – David Wolever
              Jul 11 '11 at 23:57











            • @David Wolever: Seems like coding a RawIOBase-like wrapper for your iterable and passing that to BufferReader would be feasible. RawIOBase objects only have 4 methods and you might be able to get away with only implementing the 3 read...() ones.

              – martineau
              Jul 12 '11 at 0:33


















            4














            A starting point:



            class iterable_to_stream:
            def __init__(self, iterable):
            self.iter = iter(iterable)

            def read(self):
            try:
            return self.iter.next()
            except StopIteration:
            return ""





            share|improve this answer
























            • Hhmm… While that would most certainly explode on its own (what if next(iter) returns ""? What if someone has the audacity to pass a size into read(…))… I guess I could use a BufferedReader to take care of those details…

              – David Wolever
              Jul 11 '11 at 23:40











            • Sorry dude, this appears to be unworkable. BufferedReader needs an instance of RawIOBase, and this doesn't come anywhere near to implementing that interface… And it doesn't even implement the basic stream API (eg, read() doesn't accept a size).

              – David Wolever
              Jul 11 '11 at 23:57











            • @David Wolever: Seems like coding a RawIOBase-like wrapper for your iterable and passing that to BufferReader would be feasible. RawIOBase objects only have 4 methods and you might be able to get away with only implementing the 3 read...() ones.

              – martineau
              Jul 12 '11 at 0:33
















            4












            4








            4







            A starting point:



            class iterable_to_stream:
            def __init__(self, iterable):
            self.iter = iter(iterable)

            def read(self):
            try:
            return self.iter.next()
            except StopIteration:
            return ""





            share|improve this answer













            A starting point:



            class iterable_to_stream:
            def __init__(self, iterable):
            self.iter = iter(iterable)

            def read(self):
            try:
            return self.iter.next()
            except StopIteration:
            return ""






            share|improve this answer












            share|improve this answer



            share|improve this answer










            answered Jul 11 '11 at 23:23









            ClaudiuClaudiu

            127k125394584




            127k125394584













            • Hhmm… While that would most certainly explode on its own (what if next(iter) returns ""? What if someone has the audacity to pass a size into read(…))… I guess I could use a BufferedReader to take care of those details…

              – David Wolever
              Jul 11 '11 at 23:40











            • Sorry dude, this appears to be unworkable. BufferedReader needs an instance of RawIOBase, and this doesn't come anywhere near to implementing that interface… And it doesn't even implement the basic stream API (eg, read() doesn't accept a size).

              – David Wolever
              Jul 11 '11 at 23:57











            • @David Wolever: Seems like coding a RawIOBase-like wrapper for your iterable and passing that to BufferReader would be feasible. RawIOBase objects only have 4 methods and you might be able to get away with only implementing the 3 read...() ones.

              – martineau
              Jul 12 '11 at 0:33





















            • Hhmm… While that would most certainly explode on its own (what if next(iter) returns ""? What if someone has the audacity to pass a size into read(…))… I guess I could use a BufferedReader to take care of those details…

              – David Wolever
              Jul 11 '11 at 23:40











            • Sorry dude, this appears to be unworkable. BufferedReader needs an instance of RawIOBase, and this doesn't come anywhere near to implementing that interface… And it doesn't even implement the basic stream API (eg, read() doesn't accept a size).

              – David Wolever
              Jul 11 '11 at 23:57











            • @David Wolever: Seems like coding a RawIOBase-like wrapper for your iterable and passing that to BufferReader would be feasible. RawIOBase objects only have 4 methods and you might be able to get away with only implementing the 3 read...() ones.

              – martineau
              Jul 12 '11 at 0:33



















            Hhmm… While that would most certainly explode on its own (what if next(iter) returns ""? What if someone has the audacity to pass a size into read(…))… I guess I could use a BufferedReader to take care of those details…

            – David Wolever
            Jul 11 '11 at 23:40





            Hhmm… While that would most certainly explode on its own (what if next(iter) returns ""? What if someone has the audacity to pass a size into read(…))… I guess I could use a BufferedReader to take care of those details…

            – David Wolever
            Jul 11 '11 at 23:40













            Sorry dude, this appears to be unworkable. BufferedReader needs an instance of RawIOBase, and this doesn't come anywhere near to implementing that interface… And it doesn't even implement the basic stream API (eg, read() doesn't accept a size).

            – David Wolever
            Jul 11 '11 at 23:57





            Sorry dude, this appears to be unworkable. BufferedReader needs an instance of RawIOBase, and this doesn't come anywhere near to implementing that interface… And it doesn't even implement the basic stream API (eg, read() doesn't accept a size).

            – David Wolever
            Jul 11 '11 at 23:57













            @David Wolever: Seems like coding a RawIOBase-like wrapper for your iterable and passing that to BufferReader would be feasible. RawIOBase objects only have 4 methods and you might be able to get away with only implementing the 3 read...() ones.

            – martineau
            Jul 12 '11 at 0:33







            @David Wolever: Seems like coding a RawIOBase-like wrapper for your iterable and passing that to BufferReader would be feasible. RawIOBase objects only have 4 methods and you might be able to get away with only implementing the 3 read...() ones.

            – martineau
            Jul 12 '11 at 0:33













            0














            TarFile takes anything that provides a file-like interface -- so you could either use StringIO (io.StringIO if you are using Python 3.X) to yield what you need to TarFile.addfile() or you could create your own class that provides a file-like interface and yields what you need.






            share|improve this answer
























            • Right — but is there any way to stream an iterator through a StringIO? I'd rather not load the entire input file into memory before writing it to the StringIO.

              – David Wolever
              Jul 11 '11 at 23:38













            • @David -- not that I know of. I'd give you an example of wrapping a class around StringIO, but it looks like you've got what you need already :-)

              – Sean Vieira
              Jul 12 '11 at 0:18
















            0














            TarFile takes anything that provides a file-like interface -- so you could either use StringIO (io.StringIO if you are using Python 3.X) to yield what you need to TarFile.addfile() or you could create your own class that provides a file-like interface and yields what you need.






            share|improve this answer
























            • Right — but is there any way to stream an iterator through a StringIO? I'd rather not load the entire input file into memory before writing it to the StringIO.

              – David Wolever
              Jul 11 '11 at 23:38













            • @David -- not that I know of. I'd give you an example of wrapping a class around StringIO, but it looks like you've got what you need already :-)

              – Sean Vieira
              Jul 12 '11 at 0:18














            0












            0








            0







            TarFile takes anything that provides a file-like interface -- so you could either use StringIO (io.StringIO if you are using Python 3.X) to yield what you need to TarFile.addfile() or you could create your own class that provides a file-like interface and yields what you need.






            share|improve this answer













            TarFile takes anything that provides a file-like interface -- so you could either use StringIO (io.StringIO if you are using Python 3.X) to yield what you need to TarFile.addfile() or you could create your own class that provides a file-like interface and yields what you need.







            share|improve this answer












            share|improve this answer



            share|improve this answer










            answered Jul 11 '11 at 23:27









            Sean VieiraSean Vieira

            115k24227230




            115k24227230













            • Right — but is there any way to stream an iterator through a StringIO? I'd rather not load the entire input file into memory before writing it to the StringIO.

              – David Wolever
              Jul 11 '11 at 23:38













            • @David -- not that I know of. I'd give you an example of wrapping a class around StringIO, but it looks like you've got what you need already :-)

              – Sean Vieira
              Jul 12 '11 at 0:18



















            • Right — but is there any way to stream an iterator through a StringIO? I'd rather not load the entire input file into memory before writing it to the StringIO.

              – David Wolever
              Jul 11 '11 at 23:38













            • @David -- not that I know of. I'd give you an example of wrapping a class around StringIO, but it looks like you've got what you need already :-)

              – Sean Vieira
              Jul 12 '11 at 0:18

















            Right — but is there any way to stream an iterator through a StringIO? I'd rather not load the entire input file into memory before writing it to the StringIO.

            – David Wolever
            Jul 11 '11 at 23:38







            Right — but is there any way to stream an iterator through a StringIO? I'd rather not load the entire input file into memory before writing it to the StringIO.

            – David Wolever
            Jul 11 '11 at 23:38















            @David -- not that I know of. I'd give you an example of wrapping a class around StringIO, but it looks like you've got what you need already :-)

            – Sean Vieira
            Jul 12 '11 at 0:18





            @David -- not that I know of. I'd give you an example of wrapping a class around StringIO, but it looks like you've got what you need already :-)

            – Sean Vieira
            Jul 12 '11 at 0:18


















            draft saved

            draft discarded




















































            Thanks for contributing an answer to Stack Overflow!


            • Please be sure to answer the question. Provide details and share your research!

            But avoid



            • Asking for help, clarification, or responding to other answers.

            • Making statements based on opinion; back them up with references or personal experience.


            To learn more, see our tips on writing great answers.




            draft saved


            draft discarded














            StackExchange.ready(
            function () {
            StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f6657820%2fhow-to-convert-an-iterable-to-a-stream%23new-answer', 'question_page');
            }
            );

            Post as a guest















            Required, but never shown





















































            Required, but never shown














            Required, but never shown












            Required, but never shown







            Required, but never shown

































            Required, but never shown














            Required, but never shown












            Required, but never shown







            Required, but never shown







            Popular posts from this blog

            Costa Masnaga

            Fotorealismo

            Sidney Franklin