Join GitHub today
GitHub is home to over 31 million developers working together to host and review code, manage projects, and build software together.
Sign up`print!` macro should flush stdout #23818
Comments
This comment has been minimized.
This comment has been minimized.
|
As a quick survey, standard output is line buffered in C, C++, Python, and Ruby. Go's |
This comment has been minimized.
This comment has been minimized.
|
I opened #23823. It's not entirely clear to me that the solution isn't to just update the docs to point out that stdout in unbuffered, but I think at the point where you're invoking the |
This comment has been minimized.
This comment has been minimized.
|
Sure, but that's orthogonal, since the underlying fd is not, and writing to it will not emit anything until it's flushed. I'm pretty sure that the correct approach is to merge that patch, but figured it was worth pointing out that updating the docs may be a valid approach too. |
This comment has been minimized.
This comment has been minimized.
|
It's not 100% clear to me that this is the behavior that we want. In #23087 it was explicitly removed due to worries about deadlocking. The specific problem of deadlocking can be papered over, but in general APIs tend to work much better over time if they do precisely what you expect, and it may not always be expected that One downside of flushing on I would be fine beefing up the documentation in this regard, of course! |
This comment has been minimized.
This comment has been minimized.
|
That's totally reasonable, and mostly what I expected. Do you have a Will update the docs if no one beats me to it. On Saturday, March 28, 2015, Alex Crichton notifications@github.com wrote:
|
richo
referenced this issue
Mar 29, 2015
Merged
std: Add a note about the print! macro and output buffering #23826
This comment has been minimized.
This comment has been minimized.
|
While making the documentation clearer would certainly be helpful, I think Rust is losing ease of use by making auto-flushing more difficult than need be. C++ has |
This comment has been minimized.
This comment has been minimized.
|
Could there be new macros for this use case? I'd hate for Rust I/O to be harder to use correctly than C++'s especially in a common learning case. For example, since C++ does flush #include <iostream>
int main() {
std::cout << "Type something: ";
std::string input;
std::cin >> input;
std::cout << input << std::endl;
} Also according to the C standard:
|
This comment has been minimized.
This comment has been minimized.
I generally really dislike implicit flushing and prefer to flush explicitly. On the other hand, there’s |
steveklabnik
added
the
I-papercut
label
Mar 30, 2015
This comment has been minimized.
This comment has been minimized.
The design here is generally mostly about trade-offs. On one hand you have "ease of use" where you don't have to worry about calling For example, what should this code do? let input = io::stdin();
let mut locked = input.lock();
print!("enter input: ");
let mut input = String::new();
try!(locked.read_line(&mut input));
println!("you entered: {}", input);If |
This comment has been minimized.
This comment has been minimized.
I think you misunderstood what the issue is about: it is only proposed to flush std_out_ after macro_rules! print(…) {
…
}to macro_rules! print(…) {
…
stdout().flush()
}Since let output = io::stdout();
let output = output.lock();
print!("stdout locked"); // deadlock.I’m starting to believe that stabilising |
This comment has been minimized.
This comment has been minimized.
Hm yes, I think I have misunderstood! There are definitely performance considerations which affect flush-on-all-print semantics as it's not something that other languages tend to do and can greatly hinder various benchmarks. |
This comment has been minimized.
This comment has been minimized.
|
I think the crux of this is basically "What is the intent of print!". My While I don't believe it's actually on the table, I would be a stoic -1 to On Mon, Mar 30, 2015 at 1:50 PM, Alex Crichton notifications@github.com
|
This comment has been minimized.
This comment has been minimized.
|
To address the performance considerations, could the |
Manishearth
added a commit
to Manishearth/rust
that referenced
this issue
Mar 31, 2015
This comment has been minimized.
This comment has been minimized.
|
@tanadeau unfortunately it's a performance concern both attached and not attached to a TTY |
tanadeau
referenced this issue
Apr 3, 2015
Merged
Implement reentrant mutexes and make stdio use them #24029
This comment has been minimized.
This comment has been minimized.
|
I'm against this. Implicit flushing will degrade performance of programs doing specifically What, for example, do you use for actual text printing of your main output in console programs? I used About buffering: this man mentions the defaults |
barosl
referenced this issue
May 17, 2015
Closed
stdout/stderr should be flushed when reading from stdin #25555
jbcrail
added a commit
to jbcrail/coreutils
that referenced
this issue
May 30, 2015
jbcrail
added a commit
to jbcrail/coreutils
that referenced
this issue
May 30, 2015
jbcrail
referenced this issue
May 30, 2015
Merged
Ensure any pending stdout writes are flushed. #629
nikklassen
referenced
this issue
in nikklassen/Splash
Jun 7, 2015
This comment has been minimized.
This comment has been minimized.
softprops
commented
Dec 11, 2015
|
Fwiw Ive run into this more than a few times and each time it was confusing as a user. Its the same kind of confusion you'd have if you pushed a print button in your browser and nothing happens. I think part of a compromised solution lies in a more meaningful name. We have buffered readers and writers for the performance mentioned above and do not cause the same kind of confusion because their names reveal their expected behavior. What about a bufprint macro you can call when you want buffering and have print's default behavior be to... print something. |
This comment has been minimized.
This comment has been minimized.
BartMassey
commented
May 17, 2017
|
Hey, I just hit this too! Maybe a sufficient compromise that would make everybody reasonably happy is just a I'd prefer that |
This comment has been minimized.
This comment has been minimized.
|
I feel that some of the confusion comes from the fact that A solution would be to make
Line buffering has its uses, but I feel like it's trying to be smart but it's really just making things more complicated. |
Mark-Simulacrum
added
C-feature-request
and removed
I-papercut
labels
Jul 22, 2017
This comment has been minimized.
This comment has been minimized.
aalub
commented
Nov 8, 2017
•
|
To flush or not to flush... That is the question! (C) Gentlemen, I'm fully aware the #23823 #25555 are closed, but I have a question on the same thing: How can I write simple and consistent code like C's char str_in[1024];
printf("enter some text: ");
gets(str_in);
printf("your input is \"%s\"", str_in);in Rust? Which would let me input some text on the same line with the prompt for it, without using I try to call Which seems very strange for an outsider to Rust. Thanks in advance. p.s. Flushing the console buffer just before reading it (at any form) seemed a good idea, but it was rejected. I failed to understand why. |
This comment has been minimized.
This comment has been minimized.
These kinds of questions are better served by https://users.rust-lang.org/ than the issue tracker. |
This comment has been minimized.
This comment has been minimized.
BartMassey
commented
Nov 9, 2017
|
The problem here is that a bunch of new Rust users are going to be confused by behavior that isn't well-documented and in my opinion a bit surprising, without being given any warning in any official documentation, and without being given any obvious path to do what is a very common operation: printing a prompt and getting a response. Python's solution is to have the use std::io::{stdin, stdout, Write};
fn main() {
print!("prompt: ");
stdout().flush().unwrap();
let mut guess = String::new();
stdin().read_line(&mut guess).unwrap();
println!("got {}", guess);
}(You could just I see this level of fiddly complexity for a common operation routinely performed by beginning programmers as a real issue that needs to be addressed directly. Documenting the above example and giving it the page of explanation that it deserves just doesn't seem like enough to me. The fact that the last I don't care too much about how this is addressed, but it should be somehow. Regardless of whether consensus can be reached, by all means at least hack up "Guessing Game" to do this so there's a standard example. But I'd strongly prefer a solution that makes "Guessing Game" prettier. |
This comment has been minimized.
This comment has been minimized.
aalub
commented
Nov 9, 2017
•
Sorry. But my How can I question arouses out from the decision not to flush Constructing complex output by multiple sequential Another common task is interacting with the user, and the Guessing Game is a good example (a less naughty example is Rust's installer for Windows). Such a task can duly interleave the program's output with the user's input and it seems a good practice to grant the programmer a proper tool for it. Using something like print() and read() functions seems to be the solution, but with Rust it is an illusion: the programmer is obliged to bother with flushing unfinished lines of So why this flushing should not be seamlessly placed before every read inside Rust library? It seems obvious that before reading the user's input all the program's output ought to be flushed: the user has to see what [s]he asked for. Apropos, if the library flushes Or, if there is other proper practice of interacting with the user - which is it? Using strict Whence my "How can I...?". I fully agree with @BartMassey's conclusion above except that I emphasize the only place for flush is not after writing but before reading user's input, which is very slow by nature, where there is plenty of time to do anything useful. @BartMassey, thank you for example and explanations! I feel the issue is still not settled. |
This comment has been minimized.
This comment has been minimized.
BartMassey
commented
Nov 9, 2017
There are other places where some kind of convenient flush would be useful. One example is printing some non-line-terminated string before an expensive computation. print!("The answer is (please wait)... ");
println!("{}", expensive_function());I'm not too dogmatic about what's done about these cases, but I feel like at least one of the solutions proposed above should be implemented. |
dtolnay
added
the
I-nominated
label
Nov 18, 2017
dtolnay
removed
I-needs-decision
I-nominated
labels
Dec 5, 2017
This comment has been minimized.
This comment has been minimized.
|
We discussed this with the libs team and our feeling was that none of the suggestions that involve an implicit flush really address the knowledge gap of people having an incorrect (or no) mental model of how buffered i/o and flushing works. These changes would just move the stumbling block to some later point when buffered i/o and flushing inevitably bites them anyway. People writing interactive command-line apps need to understand what flushing means and inserting implicit flushes would not be doing them any favors. We would welcome documentation improvements that do a better job of teaching the behavior of std::io with respect to flushing. Also we would love to consider an RFC for improving the ergonomics of explicit flushing in conjunction with |
dtolnay
closed this
Dec 5, 2017
This comment has been minimized.
This comment has been minimized.
BartMassey
commented
Dec 5, 2017
Sounds good! Should we remove the implicit flushing in In the meantime I've started on an RFC for a Python-style |
This comment has been minimized.
This comment has been minimized.
leovano
commented
Dec 8, 2017
|
For those who need to prompt the user to enter any information, why not use a crate for that? |
This comment has been minimized.
This comment has been minimized.
mstagg
commented
Dec 8, 2017
|
@leovano B/c we dont want this to turn into some javascript monstrosity of poorly stitched together libraries and frameworks. This is base level functionality, having to import a crate is way too heavy handed of a solution. |
This comment has been minimized.
This comment has been minimized.
MutantOctopus
commented
Mar 1, 2018
|
I just ran into this issue for the first time, and just to give my two cents: I generally agree with what's been said.
At the same time, I think it would be beneficial to have a separate print macro which flushes - |
This comment has been minimized.
This comment has been minimized.
BartMassey
commented
Mar 1, 2018
|
I've been quite busy lately, but I have a prototype implementation of flushing print macros and an RFC mostly written. I'll try to get it out for review in the next few weeks. If someone wants to help get it out sooner, let me know. |
This comment has been minimized.
This comment has been minimized.
|
I believe that (Also, having a |
This comment has been minimized.
This comment has been minimized.
BartMassey
commented
May 3, 2018
|
The macro names I am currently using in my draft RFC are |
This comment has been minimized.
This comment has been minimized.
satchm0h
commented
May 28, 2018
|
My guess is that a large percentage of folks will (or should) read the second edition book to get started. I would recommend changing the chapter two exercise code to use If I were to make a suggestion for a more elegant solution I would go back to @CleanCut's suggestion to add a new macro. However, I would look for something a bit terser. Maybe |
This comment has been minimized.
This comment has been minimized.
BartMassey
commented
May 28, 2018
|
My current partially-finished draft RFC has an |
This comment has been minimized.
This comment has been minimized.
|
+1 for a python-style input! macro, which takes care of the typical write-then-read case.
It's worth noting that technically |
This comment has been minimized.
This comment has been minimized.
NealEhardt
commented
Oct 19, 2018
I only have a shallow understanding of how flushing works, so please forgive the question. How will people be bitten? My guess:
Is there anything else? These issues seem trivial when I weigh them against the panic and frustration of "I'm printing stuff but it doesn't appear on-screen." The people writing performance-intensive command-line apps can use non-flushing |
RandomInsano
referenced this issue
Nov 17, 2018
Open
`print!` and friends should flush on '\r' as well as '\n' #56015
This comment has been minimized.
This comment has been minimized.
x0a
commented
Dec 13, 2018
|
What about a printf! macro that prints and then flushes? Without modifying the behavior of the print! macro |
This comment has been minimized.
This comment has been minimized.
|
I'd be okay with a macro that guarantees a flush, but I'd be concerned about naming it |
This comment has been minimized.
This comment has been minimized.
hyarsan
commented
Jan 31, 2019
|
How about |
tanadeau commentedMar 28, 2015
As stdout is line-buffered, stdout is not implicitly flushed until a new-line is encountered. This means that the
print!macro does not act like aprintln!without the newline as the documentation suggests. To be equivalent, the user must explicitly flush stdout like the following:For easy use of the print macros, the user should not need to know about how I/O flushing works. As such,
print!should explicitly flush stdout itself.