如何在 Ruby 中获取当前文件和行号?

11

我想实现一个类似这样的日志函数:

def mylog(str)
   puts __FILE__, ":"__LINENO__, ":", str  # Here how to get __FILE__ and __LINENO__ is my question.
end

当我调用mylog函数时:

mylog 'hello' # say I call this in my.rb line 10

我希望你能翻译成中文:

my.rb:10:hello

请帮助给出mylog函数的正确实现。


1
另外提一下,返回当前行号的是__LINE__(而不是__LINENO__)。 - Eric B
3个回答

16

使用 caller 是老式的做法,应该改为使用 caller_locations

def mylog(str)
  caller_locations(1, 1).first.tap{|loc| puts "#{loc.path}:#{loc.lineno}:#{str}"}
end

caller_locations需要特定的Ruby版本吗? - TieDad
1
是的。它是在 Ruby 2.0 中引入的。 - sawa

12

你需要使用caller

def mylog(str)
  caller_line = caller.first.split(":")[1]
  puts "#{__FILE__} : #{caller_line} : #{str}"  
end

你可能也想知道调用mylog的文件是哪个...

def mylog(str)
  caller_infos = caller.first.split(":")
  puts "#{caller_infos[0]} : #{caller_infos[1]} : #{str}"  
end

这个可以运行,但不是最好的。使用 caller 是老式的方法。 - sawa
对于未来的读者来说是可以的,但现在我不想假设 Ruby 2.0。 - gmalette
caller_line=caller[0].split(":")[1]; puts "#{FILE}:#{caller_line}:#{str}" FYI,你可以通过将此示例中的零递增为1、2等来遍历调用堆栈。 - Michael Dimmitt

11

获取行号的正确变量是__LINE__,因此您的函数的适当实现应该是:

def mylog(str)
 puts "#{__FILE__}:#{__LINE__}:#{str}"  
end

编辑以使输出与您的匹配


1
如果使用__FILE__是操作者误导您的错误,但这会给出包含puts方法的文件和行号。 - sawa
啊,是的,我猜我太急了,没有完全理解他想要什么。 - Teddy
为了清晰起见,注释是关于“函数定义”与“函数调用”位置的。 - Michael Dimmitt
1
虽然没有回答原问题,但对于那些想知道的人来说,这是有用的,因为谷歌会把他们带到这里。 - David Oneill

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接