-
-
Notifications
You must be signed in to change notification settings - Fork 503
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
StopIteration is not raised correctly with _iter=True #273
Comments
Your process is already an iterator, by virtue of passing
It's designed to take all the args as (presumably?) unique iterators, pull one from each, and zip it up. The fact that you're using the same iterator 10 times is strange. It means Thinking about it this way, it makes sense why the code is locking up. Your resulting iterator (the one returned from izip_longest) can only yield a value IFF it has collected 10 values from the single iterator you passed in 10 times. Let's say your process would return 6 values but you're asking for 10. When So the bug here seems to be that multiple calls to >>> p = sh.ls(_iter=True)
>>> next(p) # repeat this until StopIteration, then do it one more time In the meantime, this should accomplish the same thing you're trying to do and works correctly with sh because it stops after the process says its done. def chunk_iterator(it, times):
chunks = []
for piece in it:
chunks.append(piece)
if len(chunks) == times:
yield chunks
chunks = []
yield chunks |
Thank you for your response.
I believe so. A similar piece of code is included in the recipes section of itertools (in the grouper function). Yes, definitely calling
A regular iterator follows this behavior:
Are you sure
If I set a variable
|
>>> p = sh.ls(_iter=True)
>>> next(chunk_iterator(p, 2))
>>> next(chunk_iterator(p, 2)) Don't do that. It's creating multiple chunked iterator for the same underlying iterator. It's causing the problem of calling a completed process iterator more than once again. >>> output_iterator = sh.ls(_iter=True)
>>> chunks = chunk_iterator(output_iterator, 2)
>>> next(chunks)
>>> next(chunks) # etc That is the correct usage |
Yes, that's what I thought. Thanks. |
Sure thing, thanks for reporting the underlying bug. I'll leave this open until I fix it. |
This is on the |
Great. Thank you! |
* added `_out` and `_out_bufsize` validator [#346](amoffat/sh#346) * bugfix for internal stdout thread running when it shouldn't [#346](amoffat/sh#346) * regression bugfix on timeout [#344](amoffat/sh#344) * regression bugfix on `_ok_code=None` * further improvements on cpu usage * regression in cpu usage [#339](amoffat/sh#339) * fd leak regression and fix for flawed fd leak detection test [#337](amoffat/sh#337) * support for `io.StringIO` in python2 * added support for using raw file descriptors for `_in`, `_out`, and `_err` * removed `.close()`ing `_out` handler if FIFO detected * composed commands no longer propagate `_bg` * better support for using `sys.stdin` and `sys.stdout` for `_in` and `_out` * bugfix where `which()` would not stop searching at the first valid executable found in PATH * added `_long_prefix` for programs whose long arguments start with something other than `--` [#278](amoffat/sh#278) * added `_log_msg` for advanced configuration of log message [#311](amoffat/sh#311) * added `sh.contrib.sudo` * added `_arg_preprocess` for advanced command wrapping * alter callable `_in` arguments to signify completion with falsy chunk * bugfix where pipes passed into `_out` or `_err` were not flushed on process end [#252](amoffat/sh#252) * deprecated `with sh.args(**kwargs)` in favor of `sh2 = sh(**kwargs)` * made `sh.pushd` thread safe * added `.kill_group()` and `.signal_group()` methods for better process control [#237](amoffat/sh#237) * added `new_session` special keyword argument for controlling spawned process session [#266](amoffat/sh#266) * bugfix better handling for EINTR on system calls [#292](amoffat/sh#292) * bugfix where with-contexts were not threadsafe [#247](amoffat/sh#195) * `_uid` new special keyword param for specifying the user id of the process [#133](amoffat/sh#133) * bugfix where exceptions were swallowed by processes that weren't waited on [#309](amoffat/sh#309) * bugfix where processes that dupd their stdout/stderr to a long running child process would cause sh to hang [#310](amoffat/sh#310) * improved logging output [#323](amoffat/sh#323) * bugfix for python3+ where binary data was passed into a process's stdin [#325](amoffat/sh#325) * Introduced execution contexts which allow baking of common special keyword arguments into all commands [#269](amoffat/sh#269) * `Command` and `which` now can take an optional `paths` parameter which specifies the search paths [#226](amoffat/sh#226) * `_preexec_fn` option for executing a function after the child process forks but before it execs [#260](amoffat/sh#260) * `_fg` reintroduced, with limited functionality. hurrah! [#92](amoffat/sh#92) * bugfix where a command would block if passed a fd for stdin that wasn't yet ready to read [#253](amoffat/sh#253) * `_long_sep` can now take `None` which splits the long form arguments into individual arguments [#258](amoffat/sh#258) * making `_piped` perform "direct" piping by default (linking fds together). this fixes memory problems [#270](amoffat/sh#270) * bugfix where calling `next()` on an iterable process that has raised `StopIteration`, hangs [#273](amoffat/sh#273) * `sh.cd` called with no arguments no changes into the user's home directory, like native `cd` [#275](amoffat/sh#275) * `sh.glob` removed entirely. the rationale is correctness over hand-holding. [#279](amoffat/sh#279) * added `_truncate_exc`, defaulting to `True`, which tells our exceptions to truncate output. * bugfix for exceptions whose messages contained unicode * `_done` callback no longer assumes you want your command put in the background. * `_done` callback is now called asynchronously in a separate thread. * `_done` callback is called regardless of exception, which is necessary in order to release held resources, for example a process pool
I found an odd case in which the return value of something like
sh.ls('-a', _iter=True)
is not behaving as a regular iterator. If I keep callingnext
on an expression with_iter=True
everything looks okay. However, when I try to iterate over chunks usingitertools.izip_longest(*([ iter(p) ] * 10))
(iterating over chunks of 10 elements), there is some point in whichnext
is not raisingStopIteration
and instead hangs the Python REPL.The interesting thing is that after interrupting the last
next
operation, if I callnext
again, then I get aStopInteration
.This is how I think it should work:
The text was updated successfully, but these errors were encountered: