【问题标题】:Inserting bash script in python code在 python 代码中插入 bash 脚本
【发布时间】:2018-08-17 10:35:29
【问题描述】:

我正在尝试从 python 代码执行 bash 脚本。 bash 脚本在 for 循环内的管道中有一些 grep 命令。当我运行 bash 脚本本身时,它没有给出任何错误,但是当我在 python 代码中使用它时,它说:grep:write 错误。

我在python中调用的命令是:

subprocess.call("./change_names.sh",shell=True)

bash 脚本是:

#!/usr/bin/env bash

for file in *.bam;do new_file=`samtools view -h $file | grep -P '\tSM:' | head -n 1 | sed 's/.\+SM:\(.\+\)/\1/' | sed 's/\t.\+//'`;rename s/$file/$new_file.bam/ $file;done

我错过了什么?

【问题讨论】:

  • 如果你也发布你的 bash 脚本可能会有所帮助
  • 更新了帖子。
  • 尝试改用subprocess.Popen()
  • 我通常使用subprocess.check_output("bash script.sh", shell=True)没有任何问题
  • 如果你避免使用 bash 并使用 pysam 来获取操作,它可能会更容易和更干净。

标签: python bash grep pipe


【解决方案1】:

当您运行一个不需要 shell 的简单命令时,您不应使用 shell=True

subprocess_call(["./change_names.sh"])

shell 脚本中存在多个问题。这是一个注释重构。

#!/usr/bin/env bash

for file in *.bam; do
    # Use modern command substitution syntax; fix quoting
    new_file=$(samtools view -h "$file" |
        grep -P '\tSM:' |
        # refactor to a single sed script
        sed -n 's/.\+SM:\([^\t]\+\).*/\1/p;q')
    # Fix quoting some more; don't use rename
    mv "$file" "$new_file.bam"
done

grep -P 在这里似乎没有必要或有用,但是如果没有输入的示例,我也不愿意将其重构到 sed 脚本中。我希望我猜对了你的sed 版本对\+\t 转义符的作用,这些转义符不是完全可移植的。

在某些情况下,这仍然会产生一个警告,指出您没有读取来自grep 的所有输出。更好的解决方案可能是将更多内容重构到您的 Python 脚本中。

import glob

for file in glob.glob('*.bam'):
    new_name = subprocess.check_output(['samtools', 'view', '-h', file])
    for line in new_name.split('\n'):
        if '\tSM:' in line:
            dest = line.split('\t')[0].split('SM:')[-1] + '.bam'
            os.rename(file, dest)
            break

【讨论】:

  • 修改后的 shell 脚本给出了预期的结果,尽管错误仍然存​​在:grep:write error:Broken pipe.
  • 这是一个无害的警告,表明您没有读取来自grep 的所有输出。如果您认为这很重要,则可以避免;但同样,我在这里推荐完全避免grep
【解决方案2】:

您好,请尝试以下修改,这将解决您的问题。

for file in *.bam;do new_file=`unbuffer samtools view -h $file | grep -P '\tSM:' | head -n 1 | sed 's/.\+SM:\(.\+\)/\1/' | sed 's/\t.\+//'`;rename s/$file/$new_file.bam/ $file;done

或者尝试将标准错误重定向到 dev/null,如下所示

for file in *.bam;do new_file=`samtools view -h $file >2>/dev/null | grep -P '\tSM:' | head -n 1 | sed 's/.\+SM:\(.\+\)/\1/' | sed 's/\t.\+//'`;rename s/$file/$new_file.bam/ $file;done

您的实际问题在于此命令 samtools view -h $file 当您从 python 运行脚本时,您应该提供如下所示的完整路径:-

/fullpath/samtools view -h $file 

【讨论】:

  • 使用 unbuffer 会出错。你能解释一下为什么命令 samtools view -h $file 是实际问题吗?
  • 如果一个标准错误重定向到 grep 命令它给出grep:write error。你试过/fullpath/samtools view -h $file 吗?
  • 我尝试使用 /fullpath/samtools view -h $file 但它给出了相同的错误:grep:write error:Broken pipe。但是,结果是正确的。
  • 这会保留原始代码中的所有引用错误。不要使用这个。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-09-13
  • 2023-03-07
  • 2018-02-20
  • 1970-01-01
相关资源
最近更新 更多