arg2 = f'cat <(grep \'#\' temp2.vcf) <(sort <(grep -v \'#\' temp2.vcf) | sortBed -i - | uniq ) > out.vcf'
print(arg2)
try:
subprocess.call(arg2,shell=True)
except Exception as error:
print(f'{error}')
While I'm running this I get the following error:
/bin/sh: -c: line 0: syntax error near unexpected token `('
/bin/sh: -c: line 0: `cat <(grep '#' temp2.vcf) <(sort <(grep -v '#' temp2.vcf) | sortBed -i - | uniq ) > Out.vcf'
but when I run in the command line it works.
CodePudding user response:
The immediate error is that your attempt uses Bash-specific syntax. You can work around that with an executable="/bin/bash"
keyword argument; but really, why are you using a complex external pipeline here at all? Python can do all these things except sortBed
natively.
with open("temp2.vcf", "r"
) as vcfin, open("out.vcf", "w") as vcfout:
sub = subprocess.Popen(
["sortBed", "-i", "-"],
text=True,
stdin=subprocess.PIPE,
stdout=subprocess.PIPE)
for line in vcfin:
if "#" in line:
vcfout.write(line)
else:
sub.stdin.write(line)
subout, suberr = sub.communicate()
if suberr is not None:
sys.stderr.write(suberr)
seen = set()
for line in subout.split("\n"):
if line not in seen:
vcfout.write(line "\n")
seen.add(line)
The Python reimplementation is slightly clunkier (and untested, as I don't have sortBed
or your input data) but that also means it's more obvious where to change something if you want to modify it.
CodePudding user response:
Python's call()
function invokes the command with sh
by default. The process substitution syntax is supported by bash
, but not by sh
.
$ sh -c "cat <(date)"
sh: -c: line 0: syntax error near unexpected token `('
sh: -c: line 0: `cat <(date)'
$ bash -c "cat <(date)"
Mon Mar 14 11:12:48 PDT 2022
I suggest rewriting your command as a more conventional pipeline, something like this:
arg2 = 'grep -v "#" temp2.vcf | sortBed -i - | uniq > out.vcf'
It looks like you have some redundant steps in your command anyway.
If you really need to use the bash-specific syntax, you should be able to specify the shell executable (but I have not tried this):
subprocess.call(arg2, shell=True, executable='/bin/bash')