Вот чистая Python переопределение.
with open(go_term_file, "a") as f:
for file in glob.glob("*_protein.faa.tsv"):
f.write("Genome GO_term\n")
with open(file, "r") as file_data:
seen = set()
for line in file_data:
fields = line.strip("\n").split("\t")
try:
value = "{0}\t{1}\n".format(fields[0], fields[13]])
except IndexError:
continue
if "GO:" in value:
if value not in seen:
f.write(value)
seen.add(value)
Сценарий Awk также выиграл бы от проверки на GO:
уже в части Awk перед печатью чего-либо вообще.
Обратите внимание, что это исправляет также несколько ошибок в вашем коде Python.
Вывод subprocess.call()
просто отображается на стандартном выводе и вообще не доступен для Python; возвращаемое значение, полученное из call
, является кодом возврата конвейера оболочки (0 для успеха, другие числа означают uniq
сбой или произошла ошибка синтаксического анализа оболочки). Если вы хотите обработать вывод подпроцесса, используйте subprocess.check_output()
или его современную замену subprocess.run()
.
Вы также ничего не делали с data
, который вы прочитали, и конвейер оболочки был также не получая никакого ввода.
Стилистически, мы предпочитаем менеджер контекста with
вместо явного открытия и закрытия файлов (вы также забыли закрыть file_data
).
Ваш код будет запись Genome GO_term
один раз для каждого входного файла; Я сохранил эту логику c, но, наверное, вы не хотели, чтобы она работала таким образом. grep
в вашем оригинале отбрасывает этот вывод; конечно, если вы действительно этого не хотите, не печатайте его в первую очередь.
Аналогично, я укажу, что uniq
будет запускаться один раз для каждого входного файла, поэтому, если несколько входные файлы содержат одинаковое значение, вы получите дубликаты. Если это не то, что вам нужно, создание пустого набора seen
вне for
l oop вместо этого делает его глобальным.
... Это не было бы слишком сложно исправить в сценарии оболочки , или; просто запустите Awk для всех входных файлов в одном go. На самом деле тогда вам вообще не понадобится Python здесь (или, как отмечено выше, grep
).
awk -F "\t" 'FNR==1 {print "Genome GO_term"}
$14 ~ /GO:/ {print $1 "\t" $14}' *_protein.faa.tsv |
uniq
Обратите также внимание, что uniq
удаляет только смежные идентичные строки , В коде Python я предположил, что вы действительно хотите, чтобы каждая строка вывода была уникальной, но это должно быть легко изменить обратно (просто запомните предыдущее напечатанное значение и не печатайте, если оно идентично). И наоборот, было бы несложно реорганизовать скрипт Awk, чтобы он не печатал повторы, используя очень похожие логики c, хотя, конечно, синтаксис Awk будет сильно отличаться от того, как он выглядит в Python.
. Сравните эти два подхода, обратите внимание, насколько кратким является код Awk. Даже если вы увеличите его в четыре раза по размеру и сложности, он все равно будет довольно маленьким и простым для понимания. Но тогда это примерно предел того, что имеет смысл делать в Awk; если вы планируете сделать эту часть более крупной и сложной программы, Python больше подходит для этого. Кроме того, код Python, во всей своей очевидности, довольно легко понять, даже если вы не используете язык каждый день. Боюсь, этого нельзя сказать об Awk. Явная структура кода Python также позволяет легко определить, какая часть может потребоваться изменить, если вы обнаружите или обнаружите новые требования.