触发段错误时pytest输出缺失,且重定向stderr至stdout并经head过滤时部分输出丢失的原因咨询
你遇到的问题本质上和2>&1重定向本身无关,而是**head命令的行为+Linux管道的信号机制**共同作用的结果,具体拆解如下:
1. head的“急性子”导致管道提前关闭
当你用| head -n15时,head会在读取到15行输入后立刻关闭管道的读取端,然后直接退出——它才不管后面还有没有数据要写呢。
2. pytest收到SIGPIPE信号直接终止
Linux系统中,当一个进程尝试往已经被关闭的管道写数据时,会收到SIGPIPE(管道破裂)信号。默认情况下,进程收到这个信号会直接终止,根本来不及输出剩下的内容。
在你的场景里,2>&1把pytest的所有输出(包括原本在stderr的测试框架日志,以及在stdout的测试代码print内容)都合并到了管道里。head读完前15行(刚好是测试会话启动的那些日志)就关了管道,此时pytest还在输出测试过程中的调试信息(比如compressor = libnvcomp.LZ4Compressor(stream=s)这些行),一写管道就触发SIGPIPE,直接被杀死,自然这些内容就消失了。
3. 为什么去掉head就正常?
没有head的时候,管道的读取端会一直保持打开,直到pytest自己运行结束(哪怕触发段错误)。所以pytest能完整输出所有内容,包括段错误前的所有调试信息。
解决办法
如果想限制输出行数,同时又不想让pytest被提前终止,可以试试这几种方案:
方案1:先把输出写入临时文件,再读取前15行
这样pytest能完整输出所有内容到文件,head只是读取文件的前15行,不会干扰pytest的运行:
find . -name "*.py" | entr -s "pytest -s tests/test_nvcomp.py::test_lz4_newlib 2>&1 > /tmp/pytest_temp.log; head -n15 /tmp/pytest_temp.log"
方案2:让pytest忽略SIGPIPE信号
通过bash的trap命令让pytest在收到SIGPIPE时不终止,不过这种方法可能会让输出有残留,仅供参考:
find . -name "*.py" | entr -s "trap '' PIPE; pytest -s tests/test_nvcomp.py::test_lz4_newlib 2>&1 | head -n15"
方案3:用pytest自身参数控制输出长度
如果只是想减少输出,可以用pytest的内置参数,比如--tb=short(缩短回溯信息)、-q(安静模式),避免依赖head:
find . -name "*.py" | entr -s "pytest -s -q tests/test_nvcomp.py::test_lz4_newlib"
内容的提问来源于stack exchange,提问作者Thomson Comer

