Я хочу сосчитать вхождения около 500 шаблонов в большой файл .fastq (59 миллионов строк). Все шаблоны имеют длину ровно 20 символов.
В unix это будет просто:
grep -F -o -f patterns.txt big_file.fastq | sort | uniq -c
Тем не менее, я sh, чтобы избежать записи временного файла шаблонов, поэтому я создал канал, используя библиотеку подпроцесса python:
from subprocess import Popen, PIPE, STDOUT
p1 = Popen(["grep", "-F", "-o", "-f", "-", "big_file.fastq"], shell = False, stdin = PIPE, stdout = PIPE, stderr= STDOUT)
p2 = Popen(["sort"], shell = False, stdin = p1.stdout, stdout = PIPE, stderr = STDOUT)
p3 = Popen(["uniq", "-c"], shell = False, stdin = p2.stdout, stdout = PIPE, stderr = STDOUT)
Затем я вызываю connect () для этого, предоставляя закодированный файлоподобный объект io.StringIO в качестве входных данных (который передается в grep команда с использованием '-'):
import io
patterns_file = io.StringIO("\n".join(patterns_list))
p3.communicate(input = patterns_file.read().encode('utf-8'))[0]
Когда я вызываю connect () для uniq, как это, это работает нормально.
Однако во время тестирования я ошибочно вызвал его в первой части трубы:
p1.communicate(input = patterns_file.read().encode('utf-8'))[0]
Это дало мне совершенно неверные результаты, включая совпадения, которые были короче или длиннее ожидаемых 20 символов.
Я не понимаю, почему это так. Разве вызов метода connect () на p1 не затрагивает только эту часть канала и игнорирует остальные? Удаление p2 и p3 привело к корректному отображению p1. Я чувствую, что что-то упускаю из-за того, как работает Попен.
Любая помощь приветствуется.