[英]Does Ruby use $stdout for writing the output of puts and return?
I want to know the output stream being used by Ruby to print these things at the command-line: 我想知道Ruby使用的输出流在命令行打印这些东西:
irb(main):001:0> a="test"
=> "test"
irb(main):002:0> puts a
test
=> nil
irb(main):003:0> a
=> "test"
Is $stdout
used for irb(main):002:0>
and irb(main):003:0>
? $stdout
用于irb(main):002:0>
和irb(main):003:0>
? And, is there any change in the value of $stdout
between those two invocations? 并且,这两次调用之间
$stdout
的值是否有任何变化?
Also, can some one point me to the Ruby source from where these things get printed/written? 还有,有人可以指出我从这些东西打印/写入的Ruby源代码?
Yes. 是。 And it's easy to test/prove to yourself.
并且很容易测试/证明自己。 Try this at the command-line:
在命令行尝试此操作:
ruby -e 'puts "foo"' > test.out
cat test.out
The output will be: 输出将是:
foo
Ruby uses the STDOUT channel to output to the console. Ruby使用STDOUT通道输出到控制台。 The OS then redirects that STDOUT to "test.out".
操作系统然后将该STDOUT重定向到“test.out”。
Try it with: 尝试使用:
ruby -e 'STDOUT.puts "foo"' > test.out
and you'll get the same result. 你会得到相同的结果。
If we do: 如果我们这样做:
ruby -e 'STDERR.puts "foo"' > test.out
foo
cat test.out
You'll see nothing in the file, but "foo" will have been written to the console on the STDERR channel. 您将在文件中看不到任何内容,但“foo”将被写入STDERR频道的控制台。
Ruby defines $stdout
as a global you can change, and STDOUT
as a constant, which you shouldn't change. Ruby将
$stdout
定义$stdout
可以更改的全局,将STDOUT
定义为常量,不应更改。 Similarly, $stderr
and STDERR
are available. 同样,
$stderr
和STDERR
可用。
Now, here's where it gets fun, and proves your question. 现在,这里变得有趣,并证明你的问题。 Try this:
试试这个:
ruby -e '$stdout = STDERR; puts "foo"' > test.out
and you'll have the same results as when I output to STDERR
, because, at puts
was using the value for $stdout
to select the output stream, and wrote to STDERR. 并且你将得到与输出到
STDERR
时相同的结果,因为,在puts
中使用$stdout
的值来选择输出流,并写入STDERR。 Those stream values are picked up by Ruby from the OS when the interpreter starts, and are remembered during the run-time of the script. 当解释器启动时,Ruby会从操作系统中获取这些流值,并在脚本运行时记住这些值。 You can change them if necessary and Ruby will forget those settings when the interpreter exits, and reset itself to its normal state the next time.
如果需要 ,您可以更改它们,Ruby将在解释器退出时忘记这些设置,并在下次将其自身重置为正常状态。
You shouldn't rely on the implied/invisible behavior of changing $stdout
though, because that leads to REALLY confusing code. 您不应该依赖于更改
$stdout
的隐含/不可见行为,因为这会导致真正令人困惑的代码。 Instead, I'd strongly recommend using an explicit STDERR.puts
any time you're writing to STDERR and a bare puts
for normal output to STDOUT. 相反,我强烈建议您在写入STDERR时使用显式
STDERR.puts
, puts
正常输出用于STDOUT。 If you're intermingling output to both, then it'd probably be clearer to use STDOUT.puts
and STDERR.puts
, but that's your call. 如果你将输出混合到两者,那么使用
STDOUT.puts
和STDERR.puts
可能会更清楚,但那是你的调用。
Now, IRB is the same as a regular script running in the interpreter is, as far as using $stdout
so writing output in IRB to $stdout
works the same: 现在,IRB与在解释器中运行的常规脚本相同,就使用
$stdout
,在IRB中将$stdout
写入$stdout
工作方式相同:
irb(main):001:0> $stdout
#<IO:<STDOUT>>
irb(main):002:0> $stderr
#<IO:<STDERR>>
And: 和:
irb(main):003:0> $stdout.puts 'foo'
foo
nil
irb(main):004:0> $stderr.puts 'foo'
foo
nil
And finally: 最后:
irb(main):007:0> $stdout.isatty
true
irb(main):008:0> $stdout.isatty
true
We can't really tell any difference until we look a little lower; 在我们看起来稍低之前,我们无法区分任何差异; They're both TTY channels, with the standard STDOUT and STDERR channel numbers:
它们都是TTY频道,标准的STDOUT和STDERR频道号码:
irb(main):009:0> $stdout.fileno
1
irb(main):010:0> $stderr.fileno
2
Hopefully that helps 'splain it. 希望这有助于'摒弃它。
I just realized that IRB's reporting of the return value of puts
might be confusing you, causing you to think that the STDOUT is changing. 我刚刚意识到IRB报告
puts
的回报值可能让您感到困惑,导致您认为STDOUT正在发生变化。 That nil
is returned has nothing to do with STDOUT or STDERR. 返回的
nil
与STDOUT或STDERR无关。 It's because puts
returns nil, which is dutifully reported by IRB. 这是因为
puts
回报为零,这是由IRB尽职尽责地报道的。
The reason that happens is because IRB calls inspect on the object after each operation. 发生这种情况的原因是因为IRB在每次操作后调用对象。
See Object#inspect for full details: 有关详细信息,请参阅Object#inspect:
http://ruby-doc.org/core-2.1.0/Object.html#method-i-inspect http://ruby-doc.org/core-2.1.0/Object.html#method-i-inspect
We can prove this by overriding inspect like so: 我们可以通过覆盖检查来证明这一点:
~ $ irb
>> class Foo
>> def inspect
>> 'hi'
>> end
>> end
=> nil
>> foo = Foo.new
=> hi
The only thing in your case that's hitting $stdout is the results of your puts command. 在你的情况下唯一触及$ stdout的是你的puts命令的结果。
Hope this helps! 希望这可以帮助!
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.