You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用Ruby Fiber读取文件时出现意外输出结果的问题咨询

问题成因

输出File实例信息是Ruby方法返回值规则与Fiber运行机制共同导致的,核心逻辑:

  • Ruby中所有方法执行完毕都有返回值,File#each完成全文件行遍历后,返回值是调用该方法的File实例自身。
  • Fiber执行规则:当Fiber块内所有代码运行完成、没有触发新的Fiber.yield时,Fiber会把块内最后一个表达式的结果作为本次resume的返回值,随即进入终止状态,后续再调用resume就会抛出attempt to resume a terminated fiber错误。

逐轮对应代码执行流程和输出的匹配关系:

  1. 首次调用sg.resume进入Fiber,触发文件名输入提示,输入datafile后打开目标文件,启动each遍历,读到第一行时触发Fiber.yield,将第一行文本返回外层打印。
  2. 后续连续4次调用sg.resume时,each块依次读取剩余4行内容,逐行通过Fiber.yield返回,因此依次打印文件内剩下的4行内容。
  3. 5行内容全部遍历完成后,File#each执行结束,返回对应的File实例。此时Fiber块内无剩余代码,因此第6次调用sg.resume拿到的返回值就是这个File实例,被外层puts打印,即出现#<File:0x0000557ce26ce3c8>这行输出。
  4. 本次resume执行完后Fiber已处于终止状态,下一轮循环再次调用sg.resume时触发错误,被异常捕获逻辑打印。
写法优化

原始代码存在隐含的资源泄漏问题:未给File.open传入代码块,打开的文件句柄不会主动关闭,需要等待GC回收才会释放。建议使用块形式打开文件自动管理句柄,如果不需要额外的返回值,可以在遍历结束后主动返回nil,避免File实例被意外打印:

sg = Fiber.new do
  print "Enter filename: "
  filename = gets.chomp
  File.open(filename) do |f|
    f.each { |line| Fiber.yield line }
  end
  nil
end

如果希望遍历结束后循环正常退出、不触发终止fiber的错误,可以在Fiber块末尾主动抛出StopIteration异常,loop会自动捕获该异常正常终止,不需要额外的全局rescue。

内容的提问来源于stack exchange,提问作者user3158810

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.30 06:42:29