通过Python Subprocess运行Shell脚本时ANSI转义码异常问题
Perl脚本命令行参数混入ANSI转义码导致文件无法打开(Subprocess运行异常)
问题背景
用Python的subprocess模块构建生物信息学流水线(调用.sh脚本实现并行计算),6个月前运行正常,现在出现异常:部分Perl脚本的命令行参数被插入[35m这类ANSI转义码,导致文件路径无效无法打开。直接在zsh终端运行完全相同的.sh脚本无问题,尝试多种subprocess启动方式均未解决。
错误日志(Subprocess运行)
2024-06-27 13:16:29 /Users/kevin/VirVarSeq/map_vs_consensus.pl !---- Paired end mapping using [35m./Sample_Q23.17-NHG_3BNC-10_E8-240314/Q23.17-NHG_3BNC-10_E8-240314_R1.fastq.gz[m[m [35m./Sample_Q23.17-NHG_3BNC-10_E8-240314/Q23.17-NHG_3BNC-10_E8-240314_R2.fastq.gz[m[m ... [M::bwa_idx_load_from_disk] read 0 ALT contigs [E::main_mem] fail to open file `[35m./Sample_Q23.17-NHG_3BNC-10_E8-240314/Q23.17-NHG_3BNC-10_E8-240314_R1.fastq.gz[m[m'.
正常日志(终端运行)
2024-06-27 13:08:04 /Users/kevin/VirVarSeq/map_vs_consensus.pl !---- Paired end mapping using ./Sample_Q23.17-NHG_3BNC-10_E8-240314/Q23.17-NHG_3BNC-10_E8-240314_R1.fastq.gz ./Sample_Q23.17-NHG_3BNC-10_E8-240314/Q23.17-NHG_3BNC-10_E8-240314_R2.fastq.gz ... [M::bwa_idx_load_from_disk] read 0 ALT contigs [M::process] read 41262 sequences (6098025 bp)...
出错前的.sh脚本内容
#!/bin/zsh #VirVarSeq Pipeline seq_header=Q23.17-NHG_3BNC-10_E8-240314 ln -s /Users/kevin/VirVarSeq/R ./ mkdir Sample_$seq_header ln -s $PWD/*fastq.gz ./Sample_$seq_header echo $seq_header > samples.txt #make directories as VirVar would have: mkdir VirVarResults mkdir VirVarResults/codon_table mkdir VirVarResults/consensus mkdir VirVarResults/map_vs_consensus mkdir VirVarResults/map_vs_ref mkdir VirVarResults/mixture_model #use bam file from lofreq mapping (unfortunately need it in SAM format): samtools view -h -o ./VirVarResults/map_vs_ref/$seq_header.sam $seq_header.bam "Q23.17-NHG" indir=. outdir=./VirVarResults samples=./samples.txt ref=/Users/kevin/Documents/Bienasz_Lab/HIV1_bNab_Env_Escape/Sequencing_analysis/Variant_calling/3BNC117/240621_MiSeqRun/Reference_Genomes/Q23.17-NHG.fasta startpos=6170 endpos=8829 region_start=6221 region_len=853 qv=0 consensus.pl --samplelist $samples --ref $ref --indir $indir --outdir $outdir --start $startpos --end $endpos >> VirVarSeq.log 2>&1
原因分析
ANSI转义码用于终端彩色输出,出现此问题的核心原因是:
- 近期更新的Perl脚本、bwa或samtools等工具默认开启了彩色输出
- Subprocess运行时的环境变量(如
TERM、COLORTERM)与zsh终端不一致,工具误判为支持彩色输出,导致转义码被混入命令行参数而非仅用于日志渲染 - Perl脚本中引入的彩色输出逻辑未判断运行环境是否为交互式终端
解决方案
1. 在.sh脚本中禁用彩色输出
在脚本开头添加环境变量,强制所有工具关闭彩色输出:
#!/bin/zsh # 禁用彩色输出 export TERM=dumb export COLORTERM= export BWA_COLOR=0 export SAMTOOLS_COLOR=0 # 原脚本内容...
2. 修改Python Subprocess的运行环境
调用subprocess时显式设置非交互式终端环境:
import subprocess import os # 复制当前环境并修改关键变量 env = os.environ.copy() env["TERM"] = "dumb" env.pop("COLORTERM", None) # 调用.sh脚本 subprocess.run(["zsh", "your_pipeline.sh"], env=env, check=True)
3. 修正Perl脚本的彩色输出逻辑
如果是Perl脚本本身输出转义码到参数,找到彩色输出的代码块,添加终端判断:
use Term::ANSIColor qw(:constants); # 仅当输出到交互式终端时启用颜色 my $enable_color = -t STDOUT; # 输出文件路径时判断 if ($enable_color) { print MAGENTA . $file_path . RESET; } else { print $file_path; }
4. 临时清理路径中的转义码
若无法修改工具或脚本,可在.sh脚本中添加路径清理函数:
# 清理字符串中的ANSI转义码 clean_ansi() { echo "$1" | sed -e 's/\x1b\[[0-9;]*m//g' } # 调用Perl脚本时使用清理后的参数 consensus.pl --samplelist $(clean_ansi $samples) --ref $(clean_ansi $ref) \ --indir $(clean_ansi $indir) --outdir $(clean_ansi $outdir) \ --start $startpos --end $endpos >> VirVarSeq.log 2>&1
内容的提问来源于stack exchange,提问作者lstbl
相关产品推荐
相关产品推荐

