stdout - 如何(暂时)捕获标准输出

标签 stdout nim-lang

如何在 Nim 中临时捕获标准输出?

我想要一个具有以下签名的模板:

template captureStdout(ident: untyped, body: untyped) = discard

这样代码(main.nim)运行时不会出现错误:

var msg = "hello"
echo msg & "1"
var s: string
captureStdout(s):
  echo msg & "2"
  msg = "ciao"
echo msg & "3"
assert s == "hello2\n"

输出应该是:

hello1
ciao3

当前的努力

目前我可以使用临时文件捕获标准输出,但无法释放回标准输出。我通过以下方式做到这一点:

template captureStdout*(ident: untyped, body: untyped) =
  discard reopen(stdout, tmpFile, fmWrite)
  body
  ident = readFile(tmpFile)

使用此 main.nim 运行时不会出现断言错误,但仅输出

hello1

在 tmpFile 中我看到:

hello2
ciao3

最佳答案

当您调用reopen时您重新分配变量 stdoutFile写入 tmpFile .

为了将输出打印到系统 STDOUT,您需要重新分配变量 stdoutFile写入您的系统 STDOUT。

因此,Linux 和 Windows 之间的答案有所不同。

对于 Linux,执行此操作的方法是使用 dup 和 dup2 C 函数来复制 stdout文件描述符并使用不同的文件(这样您就可以恢复标准输出)。 因为 dup 和 dup2 不在 system/io 中在 Nim 中,我们需要绑定(bind)到 unistd.h .

这是一个例子:

#Create dup handles
proc dup(oldfd: FileHandle): FileHandle {.importc, header: "unistd.h".}
proc dup2(oldfd: FileHandle, newfd: FileHandle): cint {.importc,
    header: "unistd.h".}

# Dummy filename
let tmpFileName = "tmpFile.txt"

template captureStdout*(ident: untyped, body: untyped) =
  var stdout_fileno = stdout.getFileHandle()
  # Duplicate stoud_fileno
  var stdout_dupfd = dup(stdout_fileno)
  echo stdout_dupfd
  # Create a new file
  # You can use append strategy if you'd like
  var tmp_file: File = open(tmpFileName, fmWrite)
  # Get the FileHandle (the file descriptor) of your file
  var tmp_file_fd: FileHandle = tmp_file.getFileHandle()
  # dup2 tmp_file_fd to stdout_fileno -> writing to stdout_fileno now writes to tmp_file
  discard dup2(tmp_file_fd, stdout_fileno)
  #
  body
  # Force flush
  tmp_file.flushFile()
  # Close tmp
  tmp_file.close()
  # Read tmp
  ident = readFile(tmpFileName)
  # Restore stdout
  discard dup2(stdout_dupfd, stdout_fileno)

proc main() =
  var msg = "hello"
  echo msg & "1"
  var s: string

  captureStdout(s):
    echo msg & "2"
    msg = "ciao"

  echo msg & "3"
  echo ">> ", s
  assert s == "hello2\n"

when isMainModule:
  main()
  # Check it works twice
  main()

关于stdout - 如何(暂时)捕获标准输出,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/64026829/

相关文章:

nim-lang - 如何在模板钩子(Hook)中使用闭包参数?

linux - 如何使用 bash 确保 user & pass 在 curl 中是正确的

java - 将java输出添加到bat文件的回显字符串

c - 如何在没有共享库的情况下挂接 gdb pretty-print ?

path - Nim(rod) 没有正确安装到路径?

console - 如何编译在没有控制台窗口的情况下运行的 Nim 应用程序?

Python 标准输出日志记录 : terminal vs bash file

python - 如何自定义 python 记录器行为?

node.js - NodeJS子进程stdout都是数字

nim-lang - 为什么 Nim 编译时没有捕获赋值错误?