英文:
Get name of function that called current function
问题
我希望能够在不减慢或使日志功能过于复杂的情况下,为记录目的获取调用日志功能的函数的函数名。
.log.err:{[x;y]x y}[-2;]
例如,如果我在函数 f1 中调用 .log.err"记录错误消息",我希望它附加函数名。这将打印"记录错误消息 f1"。
我知道我可以运行 ```value .z.s``` 并将其传递给 .log.err,但我不想向该函数添加额外的参数。有没有什么好的方法来实现这个?
英文:
I want to be able to get the function name of the function that calls the log function for logging purposes without slowing down or making the log function too complicated.
.log.err:{[x;y]x y}[-2;]
For example, if I call .log.err"log error msg" inside function f1, I want it to append the function name. So it would print "log error msg f1".
I know I could run value .z.s
and pass that through to .log.err but I don't want to add an additional argument to the function. Is there any good way to do this?
答案1
得分: 3
这是一个使用一些未记录的内部函数的替代方法(即在将来的q版本中可能会发生更改)。如果我们查看(已记录的)函数.Q.bt的代码,我们可以找到.Q.Ll
和.Q.btx
- 我们可以使用这些来获取当前的调用堆栈,而无需捕获错误。
以下是一个提取调用者的函数名称(以及文件和行号)的示例脚本:
.log.err:{[x;y]
d:dbg0[2]y;
x d[`func]," [",d[`file],":",string[d`line],"] : ",y;
}[-2]
dbg0:{[x;y]
f:first x _ .Q.btx .Q.Ll`;
d:`func`file`line!3#f[1];
d[`line]+:sum"\n"=f[2]#f[1;3];
d
}
f1:{.log.err"test"}
f2:{.log.err"test"}
.jm.f:{.log.err"test"}
注意:我们将参数2
传递给dbg0
以从调用堆栈中移除dbg0
和.log.err
,从而将顶部帧留给.log.err
的调用者。如果您将代码从dbg0
移到.log.err
而不是一个单独的函数中,您将希望将此更改为仅删除1帧,即.log.err
。
演示如下:
q)f1[]
..f1 [/home/jmcmurray/test.q:15] : test
q)f2[]
..f2 [/home/jmcmurray/test.q:16] : test
q).jm.f[]
.jm.f [/home/jmcmurray/test.q:17] : test
请注意,顶级命名空间中的函数前缀为..
以表示这一点。当然,您可以更改格式等。
对于在交互方式下定义的函数,不会显示文件和行号,而是为0,即:
q)f3:{.log.err"test"}
q)f3[]
..f3 [:0] : test
正如Terry提到的,您可能希望更多地查看回溯输出以实现更一般化的处理。
英文:
An alternative to Terry's solution, using some undocumented internal functions (i.e. could be subject to change in future versions of q). If we look at the code for the (documented) function .Q.bt, we find .Q.Ll
and .Q.btx
- we can use these to get the current call stack without trapping an error.
Here's an example script that extracts the function name (as well as file & line number) of the caller:
.log.err:{[x;y]
d:dbg0[2]y;
x d[`func]," [",d[`file],":",string[d`line],"] : ",y;
}[-2]
dbg0:{[x;y]
f:first x _ .Q.btx .Q.Ll`;
d:`func`file`line!3#f[1];
d[`line]+:sum"\n"=f[2]#f[1;3];
d
}
f1:{.log.err"test"}
f2:{.log.err"test"}
.jm.f:{.log.err"test"}
Note: we pass the arg 2
to dbg0
to remove dbg0
and .log.err
from the call stack, thus leaving the top frame as the caller of .log.err
. If you were to move the code from dbg0
into .log.err
instead of a separate function, you'd want to change this to only drop 1 frame i.e. .log.err
.
Demo of this in use:
q)f1[]
..f1 [/home/jmcmurray/test.q:15] : test
q)f2[]
..f2 [/home/jmcmurray/test.q:16] : test
q).jm.f[]
.jm.f [/home/jmcmurray/test.q:17] : test
Note that functions in top-level namespace are prefaced with ..
to indicate this. Of course you could change how this is formatted etc.
For a function defined interactively, rather than within a script, this is shown with no file & line number 0 i.e.
q)f3:{.log.err"test"}
q)f3[]
..f3 [:0] : test
Again as Terry mentioned you may want to look more at the backtrace output to generalise this.
答案2
得分: 2
Credit to Steve Caron for this approach which was posted to the k4 listbox on 2023.05.24:
f1:{a:1;.log.err"foo";a+x};
f2:{a:2;.log.err"bar";a+x};
curstack:{.Q.trp[{`err};();{3_y}]}:
.log.err:{[x;y]x y," - ",last[curstack][1;3]}[-2;];
q)f1[10]
foo - f1[10]
11
q)f2[10]
bar - f2[10]
12
I don't think this will work in every situation - you should study the backtrace output in more detail as you would likely need to generalize this a bit more. Link to documentation
英文:
Credit to Steve Caron for this approach which was posted to the k4 listbox on 2023.05.24:
f1:{a:1;.log.err"foo";a+x};
f2:{a:2;.log.err"bar";a+x};
curstack:{.Q.trp[{'err};();{3_y}]};
.log.err:{[x;y]x y," - ",last[curstack`][1;3]}[-2;];
q)f1[10]
foo - f1[10]
11
q)f2[10]
bar - f2[10]
12
I don't think this will work in every situation - you should study the backtrace output in more detail as you would likely need to generalise this a bit more. https://code.kx.com/q/ref/dotq/#trp-extend-trap
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论