简体   繁体   English

了解ruby方法$ stdout的工作方式

[英]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. putsKernel模块的一种方法,它实际上调用$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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM