How to convert an iterable to a stream?
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
add a comment |
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
I don't know streams well, but do you wantstream = 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
add a comment |
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
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
python stream iterator
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 wantstream = 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
add a comment |
I don't know streams well, but do you wantstream = 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
add a comment |
5 Answers
5
active
oldest
votes
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.
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 thepass
forreturn data
and the bug is gone.
– pi.
Sep 24 '12 at 9:33
1
No. Swap out thepass
forself.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
|
show 5 more comments
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())
add a comment |
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
+1 Nicely done!
– Sean Vieira
Jul 12 '11 at 0:19
add a comment |
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 ""
Hhmm… While that would most certainly explode on its own (what ifnext(iter)
returns""
? What if someone has the audacity to pass a size intoread(…)
)… I guess I could use aBufferedReader
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 ofRawIOBase
, 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 aRawIOBase
-like wrapper for your iterable and passing that toBufferReader
would be feasible.RawIOBase
objects only have 4 methods and you might be able to get away with only implementing the 3read...()
ones.
– martineau
Jul 12 '11 at 0:33
add a comment |
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.
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 aroundStringIO
, but it looks like you've got what you need already :-)
– Sean Vieira
Jul 12 '11 at 0:18
add a comment |
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
});
}
});
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
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
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.
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 thepass
forreturn data
and the bug is gone.
– pi.
Sep 24 '12 at 9:33
1
No. Swap out thepass
forself.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
|
show 5 more comments
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.
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 thepass
forreturn data
and the bug is gone.
– pi.
Sep 24 '12 at 9:33
1
No. Swap out thepass
forself.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
|
show 5 more comments
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.
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.
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 thepass
forreturn data
and the bug is gone.
– pi.
Sep 24 '12 at 9:33
1
No. Swap out thepass
forself.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
|
show 5 more comments
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 thepass
forreturn data
and the bug is gone.
– pi.
Sep 24 '12 at 9:33
1
No. Swap out thepass
forself.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
|
show 5 more comments
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())
add a comment |
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())
add a comment |
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())
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())
answered Nov 28 '13 at 7:22
Mechanical snailMechanical snail
19.6k107298
19.6k107298
add a comment |
add a comment |
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
+1 Nicely done!
– Sean Vieira
Jul 12 '11 at 0:19
add a comment |
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
+1 Nicely done!
– Sean Vieira
Jul 12 '11 at 0:19
add a comment |
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
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
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
add a comment |
+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
add a comment |
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 ""
Hhmm… While that would most certainly explode on its own (what ifnext(iter)
returns""
? What if someone has the audacity to pass a size intoread(…)
)… I guess I could use aBufferedReader
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 ofRawIOBase
, 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 aRawIOBase
-like wrapper for your iterable and passing that toBufferReader
would be feasible.RawIOBase
objects only have 4 methods and you might be able to get away with only implementing the 3read...()
ones.
– martineau
Jul 12 '11 at 0:33
add a comment |
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 ""
Hhmm… While that would most certainly explode on its own (what ifnext(iter)
returns""
? What if someone has the audacity to pass a size intoread(…)
)… I guess I could use aBufferedReader
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 ofRawIOBase
, 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 aRawIOBase
-like wrapper for your iterable and passing that toBufferReader
would be feasible.RawIOBase
objects only have 4 methods and you might be able to get away with only implementing the 3read...()
ones.
– martineau
Jul 12 '11 at 0:33
add a comment |
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 ""
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 ""
answered Jul 11 '11 at 23:23
ClaudiuClaudiu
127k125394584
127k125394584
Hhmm… While that would most certainly explode on its own (what ifnext(iter)
returns""
? What if someone has the audacity to pass a size intoread(…)
)… I guess I could use aBufferedReader
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 ofRawIOBase
, 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 aRawIOBase
-like wrapper for your iterable and passing that toBufferReader
would be feasible.RawIOBase
objects only have 4 methods and you might be able to get away with only implementing the 3read...()
ones.
– martineau
Jul 12 '11 at 0:33
add a comment |
Hhmm… While that would most certainly explode on its own (what ifnext(iter)
returns""
? What if someone has the audacity to pass a size intoread(…)
)… I guess I could use aBufferedReader
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 ofRawIOBase
, 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 aRawIOBase
-like wrapper for your iterable and passing that toBufferReader
would be feasible.RawIOBase
objects only have 4 methods and you might be able to get away with only implementing the 3read...()
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
add a comment |
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.
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 aroundStringIO
, but it looks like you've got what you need already :-)
– Sean Vieira
Jul 12 '11 at 0:18
add a comment |
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.
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 aroundStringIO
, but it looks like you've got what you need already :-)
– Sean Vieira
Jul 12 '11 at 0:18
add a comment |
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.
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.
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 aroundStringIO
, but it looks like you've got what you need already :-)
– Sean Vieira
Jul 12 '11 at 0:18
add a comment |
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 aroundStringIO
, 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
add a comment |
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.
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
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
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
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
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