Разница между $ stdout и STDOUT в Ruby

89

В чем разница между $stdout(перед знаком доллара) и STDOUT(заглавными буквами) в Ruby ? Что следует использовать при перенаправлении вывода и почему? То же самое $stderrи с STDERR.

Изменить: только что нашел связанный вопрос .

Jrdioko
источник
возможный дубликат В чем разница между STDIN и $ stdin в Ruby?
Железный Человек
@theTinMan В некотором роде дубликат. Однако следует отметить, что, хотя различия между $stdoutи STDOUTvs $stdinи STDINсимметричны, различия между $stdoutи $>vs $stdinи $<нет.
skalee 03

Ответы:

108

$stdout- глобальная переменная , представляющая текущий стандартный вывод. STDOUT- константа, представляющая стандартный вывод, обычно это значение по умолчанию$stdout .

Поскольку STDOUTэто константа, вы не должны переопределять ее, однако вы можете переопределить $stdoutбез ошибок / предупреждений (переопределение STDOUTвызовет предупреждение). например, вы можете:

$stdout = STDERR

То же самое касается $stderrиSTDERR


Итак, чтобы ответить на другую часть вашего вопроса, используйте глобальные переменные для перенаправления вывода, а не константы. Просто будьте осторожны, чтобы снова изменить это в своем коде, переопределение глобальных переменных может повлиять на другие части вашего приложения.

Брайан
источник
3
На самом деле, если вы хотите перенаправить вывод, вам, вероятно, следует использовать $>выходной поток по умолчанию, а не $stdout.
Jörg W Mittag
10
Просто нашел комментарий на другой вопрос , который говорит $stdoutи $>являются псевдонимами, поэтому переназначение один будет влиять на других.
jrdioko
9
@jrdioko: Вы правы. Видимо, я не только узнаю что-то новое каждый день, я еще что-то забываю каждый день :-)
Jörg W Mittag
2
И если читать дальше, похоже, что лучше использовать IO # reopen вместо простого назначения.
jrdioko
@jrdioko Как вы думаете, почему лучше использовать IO#reopenв случае $stdout? Я категорически не согласен с этим мнением. $stdout.reopenМетод мутирует его приемник , и это будет влиять , STDOUTесли вы не переназначить $stdoutраньше. Они не должны быть синонимами, в этом нет ничего плохого, если они имеют разные значения из-за назначения и повторного открытия, STDOUTвы нарушаете его цель.
skalee 03
5
  • STDOUT является глобальной константой, поэтому ее не следует изменять.
  • $stdout - это предопределенная переменная, поэтому ее можно изменить.

Если вы используете оболочку для перенаправления:

$ ruby test.rb > test.log

тогда не имеет значения, какой из них вы используете в качестве дескриптора файла для вашего скрипта, определяется до того, как ваш скрипт будет выполнен.

Однако, если вы пытаетесь изменить файловый дескриптор для STDOUT ОС из вашего Ruby-скрипта, например, для отправки вывода во вращающийся набор файлов журнала на основе текущего дня недели, тогда вам нужно убедиться, что вы используете $stdout.

шейкерlxxv
источник
5
«STDOUT - это глобальная константа, поэтому она не изменится». Это константа, которую МОЖНО изменить, но будет выдано предупреждение. STDOUT = $stderr (irb):1: warning: al#=> #<IO:<STDERR>>constant STDOUT >> STDOUT #=> #<IO:<STDERR>>
The Tin Man
Ах да, так следует сказать «так что это не должно быть изменено». Благодарность!
shakerlxxv
5

Оба $stdoutи STDOUTимеют разное значение. Документация Ruby по этой теме довольно ясна:

  • $stdout - Текущий стандартный вывод.
  • STDOUT- Стандартный вывод. Значение по умолчанию для $ stdout.

Когда вы хотите писать на стандартный вывод, вы фактически имеете в виду текущий стандартный вывод, поэтому вы должны писать в$stdout .

STDOUTтоже не бесполезен. В нем хранится значение по умолчанию для $stdout. Если вы когда-либо переназначаете $stdout, вы можете восстановить его до предыдущего значения с помощью $stdout = STDOUT.

Кроме того, есть еще одна предопределенная переменная:

  • $>- Вывод по умолчанию для print, printf, который $stdoutпо умолчанию.

Однако похоже, что в Ruby 2.3 он просто ведет себя как псевдоним для $stdout. Переназначение $stdoutизменяет значение $>и наоборот.

скали
источник