通过 Julia 中的外部函数或宏获取执行文件的路径

get path of the executed file through external function or macro in Julia

我正在尝试编写一个不带参数的辅助函数或宏来记录文件名和调用位置的行。

助手位于不同的模块中并导入到脚本中,因此 @__FILE__@__LINE__ 不会指向正确的位置。

这是我的辅助模块 trace.jl:

module Trace
export @trace, Location

struct Location
    file:: String
    line:: Integer
end

macro trace()
    return Location(abspath(PROGRAM_FILE), __source__.line)
end    

end

这是一个脚本caller.jl

include("trace.jl")
using .Trace

# putting two statements in one line so that line number is the same
println("I want: ", Location(@__FILE__, @__LINE__)); println(" I get: ", @trace)

运行 julia caller.jl 的输出如下:

D:\github\Handout.jl\src>julia caller.jl
I want: Location("D:\github\Handout.jl\src\caller.jl", 5)
 I get: Location("D:\github\Handout.jl\src\caller.jl", 5)

我不确定 PROGRAM_FILE 给我 caller.jl 是偶然还是有更多的保证?

我会更乐意从 __source__.file 中提取路径,因为 __source__.line 将我指向确切文件中的确切行,但是当我尝试时 __source__.filenothing .

文档中有两部分。 first one:

In addition to the given argument list, every macro is passed extra arguments named __source__ and __module__.

The argument __source__ provides information (in the form of a LineNumberNode object) about the parser location of the @ sign from the macro invocation.

second one:

Source location information is represented as (line line_num file_name) where the third component is optional (and omitted when the current line number, but not file name, changes).

These expressions are represented as LineNumberNodes in Julia.

有没有办法爬上 LineNumberNode 链来获取文件名而不是 nothing

也许还有一种方法可以将 %__FILE__ 的计算延迟到运行时,这样我就可以在 trace?

中使用该构造

类似讨论:

引用 __source__ 是 Julia 手册中推荐的。这是一个例子

文件f1.jl

module Trace

export @trace

macro trace()
    return QuoteNode(__source__)
end

end # module

文件f2.jl

include("f1.jl")

using .Trace

println("I want: ", (@__FILE__, @__LINE__)); println("I get: ", @trace)

x = @trace
dump(x)

println("This is not what you want: ", PROGRAM_FILE)

文件f3.jl

include("f2.jl")

运行 以上

现在看看输出:

$ julia f3.jl
I want: ("D:\f2.jl", 5)
I get: #= D:\f2.jl:5 =#
LineNumberNode
  line: Int64 7
  file: Symbol D:\f2.jl
This is not what you want: f3.jl

特别是:

  • @trace returns 你 LineNumberNode 对象有两个字段(但我知道这就是你想要的)
  • 你可以看到 PROGRAM_FILE 给了你不同的信息:它是从命令行传递给 Julia 的文件的名称(所以在我们的例子中是 f3.jl,虽然它是在 f2.jl 文件中调用,该文件由 f3.jl 编写 include)。

现在清楚了吗?

这是我根据@Bogumił Kamiński 的回答和 answer on type conversion:

得出的代码
struct Location
    file:: String
    line:: Integer
end

macro trace()
    return Location(String(__source__.file), __source__.line)
end

文档给我的印象是需要 QuoteNode 才能访问 __source__ 内容,实际上您只需将 Symbol __source__.file 转换为 String

还是不明白,为什么__source__.file一定要Symbol亲身体验,一定是有原因的。