Python 我如何知道引发异常的确切命令?

Python 我如何知道引发异常的确切命令?,python,debugging,Python,Debugging,(今天早些时候我自己提出的)相关问题:现在我知道为什么会发生这种情况,然后我想现在我该如何处理它 我看到了一些问题,如,并且很受欢迎,所以我想询问调试实践是关于这个主题的,对吗 背景 我写了一个脚本,它在N行上引发异常,从终端运行它,在脚本还在运行时在中间添加一行,并保存修改后的文件。因此,在解释器运行脚本文件时会对其进行修改。特别是将引发异常的行的行号已更改。Python解释器的错误回溯报告向我显示了脚本的“修改”版本的第n行,而不是实际的“运行”版本 最小示例 假设我运行一个脚本: 导入时间

(今天早些时候我自己提出的)相关问题:现在我知道为什么会发生这种情况,然后我想现在我该如何处理它

我看到了一些问题,如,并且很受欢迎,所以我想询问调试实践是关于这个主题的,对吗

背景

我写了一个脚本,它在N行上引发异常,从终端运行它,在脚本还在运行时在中间添加一行,并保存修改后的文件。因此,在解释器运行脚本文件时会对其进行修改。特别是将引发异常的行的行号已更改。Python解释器的错误回溯报告向我显示了脚本的“修改”版本的第n行,而不是实际的“运行”版本

最小示例 假设我运行一个脚本:

导入时间
时间。睡眠(5)
引发异常
当解释器在
时间被卡住时。sleep(5)
,我在那一行后面加了一行

所以现在我有:

导入时间
时间。睡眠(5)
打印(“你好世界”)
引发异常
然后解释器从睡眠中醒来,执行下一个命令,
raiseexception
,程序终止并执行以下回溯

回溯(最近一次呼叫最后一次):
文件“test/minimal_error.py”,第4行,在
打印(“你好世界”)
例外情况

因此,它正确地报告了行号(来自原始脚本,如果我们只有修改过的脚本,那么实际上是无用的)和错误消息(“异常”)。但它显示了一行完全错误的代码,实际上导致了错误;如果有任何帮助,应该显示
引发异常
,而不是
打印(“Hello World”)
,解释器甚至没有执行该命令

为什么这很重要 在实际操作中,我实现程序的一部分,运行它以查看该部分是否运行良好,当它仍在运行时,我将继续执行下一个必须实现的操作。当脚本抛出错误时,我必须找到导致错误的实际代码行。我通常只是阅读错误消息,并试图推断导致错误的原始代码

有时这不容易猜测,所以我将脚本复制到剪贴板,并通过在运行脚本后撤消所写内容来回滚代码,检查导致错误的行,然后从剪贴板粘贴回。有时这很烦人,因为当我运行脚本时,并不总是能够记住它的确切状态。(“我是否需要撤消更多以回滚?或者这正是我运行的脚本?”)

有时,脚本将运行10分钟以上,甚至在引发异常前一小时。在这种情况下,“通过撤消回滚”实际上是不可能的。有时,我甚至不知道在实际运行脚本之前,脚本将运行多长时间。很明显,我不能在脚本终止之前坐着不修改脚本

问题: 通过什么实践可以正确跟踪导致异常的命令

一个假设的解决方案是,每次我想要运行脚本时,都将脚本复制到一个新文件中,运行复制的版本,并继续编辑原始版本。但我觉得这太麻烦了,以至于当我需要运行一个脚本来检查它是否工作正常时,不能每十分钟做一次

另一种方法是每次我想运行git提交,这样我就可以在需要时返回并查看原始版本,但这会使提交历史变得非常肮脏,所以我认为这比另一个更糟糕

我还尝试了
python-mpdb-mscript.py
,但它显示了与普通回溯相同的“第n行的修改版本”


那么,有什么切实可行的解决方案我可以练习吗,比如说,每十分钟练习一次?

不要每次运行脚本都提交,只需使用git stashing,这样你就不会在历史记录中添加
脏提交

因此,在运行脚本之前,
git stash
检查本地更改,然后
git stash pop

了解更多关于git stash的信息

此解决方案假定正在运行的脚本位于当前分支的
头部


如果上述条件不适用,另一种解决方案是创建任意分支,调用它(运行脚本),
git stash
您尚未提交的本地更改,
签出
此新分支,
git apply stash
并运行脚本。然后签回原来的分支机构,重新应用存储并继续您的工作

您可以简单地编写一个bash脚本文件,使这个过程自动化,如下所示

git stash
git checkout -b running-script # potential param
git stash apply stash
RUN script # replace with the actual command to run the script in the background
git checkout original-branch # potential param
git stash apply stash

您可以将正在运行的脚本和原始分支作为参数传递给bash文件。

@chepner的注释有效:


我很确定实际的解决办法是“不要这样做”。不要修改正在运行的代码

作为一个相对简单的解决方法,您可以使用bash脚本(或者如果bash不可用,在您使用的任何环境中使用类似的脚本化方法)来实现这一点

对于bash,下面这样的脚本可以工作。它将文件名作为一个参数,并使用
date
创建一个唯一的临时文件名,然后将文件复制到其中并执行它。通过这种方式,您始终拥有运行代码的静态副本,并且可以使用别名使其变得简单:

filename=$1

# extract file name and extension
extension="${filename##*.}"
filename="${filename%.*}"

# create a unique temporary name (using date)
today=`date +%Y-%m-%d-%H:%M:%S` # or whatever pattern you desire
newname="$filename-$today.$extension"

# copy and run the python script
cp $1 $newname
echo "Executing from $newname..."
/path/to/python $newname

# clean it up when done, if you care to
rm $newname
然后,如果需要,您可以将其别名为
python
,这样您就不必考虑这样做,在
.bashrc
中使用类似的内容

alias python="source path/to/copy_execute.sh"
尽管给它起个不同的名字可能更好,比如

alias mypy="source path/to/copy_execute.sh"
然后,您可以使用
mypy myscript.py
运行脚本、修改并运行更多脚本,这样您就永远不会编辑当前正在执行的代码

一个缺点是,虽然此脚本在运行完成后会清理和删除文件,但它会在运行时创建大量临时文件。为了避开这个,y