[英]Understanding how ruby method $stdout works
Here is a simple ruby script, that takes input from a user and provides an output(yes, it will be refactored). 这是一个简单的ruby脚本,它从用户处获取输入并提供输出(是的,它将被重构)。 I wanted this script to provide output into a text file, rather than console window.
我希望此脚本将输出提供到文本文件中,而不是控制台窗口中。 That was accomplished, by simply adding
$stdout = File.new('out.txt', 'w')
, but I thought that this line will just describe a variable which I will use later to tell script to use it to write output into created file. 只需添加
$stdout = File.new('out.txt', 'w')
,但我认为这一行将仅描述一个变量,稍后我将使用该变量告诉脚本使用该变量来写输出进入创建的文件。
I cant find much documentation about this method and wondering how does this program knows how to write generated output into that file? 我找不到有关此方法的大量文档,并且想知道该程序如何知道如何将生成的输出写入该文件?
$stdout
is a global variable. $stdout
是全局变量。 By default it stores an object of type IO
associated with the standard output of the program (which is, by default, the console). 默认情况下,它存储与程序的标准输出关联的
IO
类型的对象(默认情况下为控制台)。
puts
is a method of the Kernel
module that actually calls $stdout.send()
and pass it the list of arguments it receives. puts
是Kernel
模块的一种方法,它实际上调用$stdout.send()
并将其收到的参数列表传递给它。 As the documentation explains, puts(obj, ...)
is equivalent to $stdout.puts(obj, ...)
. 如文档所述,
puts(obj, ...)
等效于$stdout.puts(obj, ...)
。
Your code replaces $stdout
with an object of type File
that extends class IO
. 您的代码将
$stdout
替换$stdout
File
类型的对象,该对象扩展了IO
类。 When it is created, your object opens the file out.txt
for writing and together with its inheritance from IO
it is fully compatible with the default behaviour of $stdout
. 创建对象后,您的对象会打开文件
out.txt
进行写入,并从IO
继承它,它与$stdout
的默认行为完全兼容。
Since by default, all the output goes to $stdout
, your new definition of $stdout
ensures the output is written to the file out.txt
without other changes in the code. 由于在默认情况下,所有的输出去
$stdout
,新的定义$stdout
保证了输出写入文件out.txt
没有在代码的其他变化。
$stdout
is a global variable (as indicated by $
) and according to the documentation, puts
is: $stdout
是一个全局变量(如$
),根据文档, puts
为:
Equivalent to
相当于
$stdout.puts(obj, ...)
If you assign another object to $stdout
, then Kernel#puts
will simply send puts
to that object. 如果您将另一个对象分配给
$stdout
,那么Kernel#puts
只会将puts
发送到该对象。 Likewise, print
will send write
: 同样,
print
将发送write
:
class Foo < BasicObject
def puts(*args)
::STDOUT.puts "Foo#puts called with #{args.inspect}"
end
def write(*args)
::STDOUT.puts "Foo#write called with #{args.inspect}"
end
end
$stdout = Foo.new
puts 'hello', 'world'
# Foo#puts called with ["hello", "world"]
print "\n"
# Foo#write called with ["\n"]
Note that if you assign to $stdout
, Ruby checks whether the object responds to write
. 请注意,如果您分配给
$stdout
,则Ruby会检查对象是否响应write
。 If not, a TypeError
will be raised. 否则,将
TypeError
。
It's probably worth highlighting the fact, mentioned by the other posts, that this is a global variable, and modifying it is not thread safe. 值得一提的是其他帖子提到的事实,它是一个全局变量,并且对其进行修改不是线程安全的。 For instance, if you point $stdout to a new IO stream, anything across the app (on that process thread) that would be logged to stdout will now be logged to your new IO stream.
举例来说,如果你点$标准输出到一个新的IO流,跨应用的任何 (对处理线程),将被记录到stdout现在将记录到你的新的IO流。 This can lead to multiple streams of unexpected and possibly sensitive input landing in your new IO stream.
这可能导致新的IO流中出现多个意外的输入流,并可能会出现敏感输入。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.