Как передать командную строку внутри функции? - PullRequest
0 голосов
/ 02 февраля 2020

Я пытаюсь распаковать файлы fasta.gz для работы с ними. Я создал скрипт, используя cmd, основываясь на том, что я делал раньше, но теперь я не могу работать с вновь созданной функцией. См. Ниже:

import glob
import sys
import os
import argparse
import subprocess
import gzip
#import gunzip

def decompressed_files():
    print ('starting decompressed_files')
    #files where the data is stored
    input_folder=('/home/me/me_files/PB_assemblies_for_me')
    #where I want my data to be
    output_folder=input_folder + '/fasta_files'
    if os.path.exists(output_folder):
        print ('folder already exists')
    else:
        os.makedirs(output_folder)
        print ('folder has been created')

    for f in input_folder:
        fasta=glob.glob(input_folder + '/*.fasta.gz')
        #print (fasta[0])
        #sys.exit()
        cmd =['gunzip', '-k', fasta, output_folder]
        my_file=subprocess.Popen(cmd)
        my_file.wait

decompressed_files()
print ('The programme has finished doing its job')

Но это выдает следующую ошибку:

TypeError: execv () arg 2 должно содержать только строки

Если I напишите fasta, программа ищет файл и ошибка становится:

fasta.gz: Нет такого файла или каталога

Если я go к каталог, в котором у меня есть файлы, и я набираю gunzip, name_file_fasta_gz, он прекрасно работает, но у меня есть несколько файлов в папке, и я хотел бы создать l oop. Я использовал 'cmd' прежде, как вы можете видеть в коде ниже, и у меня не было никаких проблем с ним. Код из прошлого, где мне удалось поместить строку, а не строку.

cmd=['velveth', output, '59', '-fastq.gz', '-shortPaired', fastqs[0], fastqs[1]]
#print cmd
my_file=subprocess.Popen(cmd)#I got this from the documentation.
my_file.wait()

Я буду рад узнать о других способах вставки команд linux в функцию python. Код для python 2.7, я знаю, что он старый, но он установлен на сервере на работе.

Ответы [ 2 ]

1 голос
/ 02 февраля 2020

fasta - это список, возвращаемый glob.glob(). Следовательно, cmd = ['gunzip', '-k', fasta, output_folder] создает вложенный список:

['gunzip', '-k', ['foo.fasta.gz', 'bar.fasta.gz'], output_folder]

, но execv() ожидает плоский список:

['gunzip', '-k', 'foo.fasta.gz', 'bar.fasta.gz', output_folder]

Вы можете использовать оператор концентрации списка + для создать плоский список:

cmd = ['gunzip', '-k'] + fasta + [output_folder]
0 голосов
/ 02 февраля 2020

Я не проверял это, но это может решить проблему с распаковкой с помощью команды. Команда gunzip -k предназначена для сохранения сжатого и распакованного файла, тогда для чего предназначен каталог output.

import subprocess
import gzip


def decompressed_files():
    print('starting decompressed_files')
    # files where the data is stored
    input_folder=('input')
    # where I want my data to be
    output_folder = input_folder + '/output'
    if os.path.exists(output_folder):
        print('folder already exists')
    else:
        os.makedirs(output_folder)
        print('folder has been created')

    for f in os.listdir(input_folder):
        if f and f.endswith('.gz'):
            cmd = ['gunzip', '-k', f, output_folder]
            my_file = subprocess.Popen(cmd)
            my_file.wait

print(cmd) будет выглядеть, как показано ниже

['gunzip', '-k', 'input/sample.gz', 'input/output']

У меня есть несколько файлов в папке, и я хотел бы создать l oop

Из приведенной выше цитаты вы можете распаковать несколько файлов * .gz из пути в этом каталоге. Пример кода ниже должен решить вашу проблему.

import os
import shutil
import fnmatch

def gunzip(file_path,output_path):
    with gzip.open(file_path,"rb") as f_in, open(output_path,"wb") as f_out:
        shutil.copyfileobj(f_in, f_out)


def make_sure_path_exists(path):
    try:
        os.makedirs(path)
    except OSError:
        if not os.path.isdir(path):
            raise


def recurse_and_gunzip(input_path):
    walker = os.walk(input_path)
    output_path = 'files/output'
    make_sure_path_exists(output_path)
    for root, dirs, files in walker:
        for f in files:
            if fnmatch.fnmatch(f,"*.gz"):
                gunzip(root + '/' + f, output_path + '/' + f.replace(".gz",""))


recurse_and_gunzip('files')

source

EDIT :

Использование аргументов командной строки - subprocess.Popen(base_cmd + args): выполнить дочернюю программу в новом процессе. В Unix класс использует os.execvp () -подобное поведение для выполнения дочерней программы

fasta.gz: Нет такого файла или каталога

Так что любой дополнительный элемент списка cmd рассматривается как аргумент, а gunzip будет искать файл argument.gz, следовательно, файл fasta.gz ошибки не найден.

ref и some полезные примеры

Теперь, если вы хотите передать gz-файлы в качестве аргумента командной строки, вы все равно можете сделать это с помощью приведенного ниже кода (вам может понадобиться немного poli sh в соответствии с вашими потребностями)

import argparse
import subprocess
import os


def write_to_desired_location(stdout_data,output_path):
    print("Going to write to path", output_path)
    with open(output_path, "wb") as f_out:
        f_out.write(stdout_data)


def decompress_files(gz_files):
    base_path=('files')  # my base path
    output_path = base_path + '/output'  # output path
    if os.path.exists(output_path):
        print('folder already exists')
    else:
        os.makedirs(output_path)
        print('folder has been created')

    for f in gz_files:
        if f and f.endswith('.gz'):
            print('starting decompressed_files', f)
            proc = subprocess.Popen(['gunzip', '-dc', f], stdout=subprocess.PIPE)  # d:decompress and c:stdout
            write_to_desired_location(proc.stdout.read(), output_path + '/' + f.replace(".gz", ""))


if __name__ == "__main__":
    parser = argparse.ArgumentParser()
    parser.add_argument(
        "-gzfilelist",
        required=True,
        nargs="+",  # 1 or more arguments
        type=str,
        help='Provide gz files as arguments separated by space Ex: -gzfilelist test1.txt.tar.gz test2.txt.tar.gz'
    )

    args = parser.parse_args()
    my_list = [str(item)for item in args.gzfilelist]  # converting namedtuple into list
    decompress_files(gz_files=my_list)

исполнение:

python unzip_file.py -gzfilelist test.txt.tar.gz

вывод

folder already exists
('starting decompressed_files', 'test.txt.tar.gz')
('Going to write to path', 'files/output/test.txt.tar')

Вы также можете передать несколько файлов gz, например

python unzip_file.py -gzfilelist test1.txt.tar.gz test2.txt.tar.gz test3.txt.tar.gz
...