subprocess.call () выдает ошибку «FileNotFoundError: [Errno 2] Нет такого файла или каталога» при перенаправлении stdout в файл - PullRequest
0 голосов
/ 16 января 2020

Я хочу перенаправить вывод консоли в текстовый файл для дальнейшей проверки. Задача состоит в том, чтобы извлечь TIFF-TAG из растрового файла (TIFF) и отфильтровать результаты. Для этого у меня есть несколько инструментов под рукой. Некоторые из них не являются python библиотеками, но являются инструментами командной строки, такими как «identifier» ImageMagick.

Мой пример командной строки, переданной subprocess.check_call(), был:

cmd_str = 'identify -verbose /home/andylu/Desktop/Models_Master/AERSURFACE/Input/Images/Denia_CORINE_CODE_18_reclass_NLCD92_reproj_ADAPTED_Europe_AEA.tif | grep -i "274"'

Здесь в выходных данных TIFF-TAG, созданных посредством «идентификатора», все строки, содержащие информацию о номере TAG «274», должны отображаться либо в консоли, либо записываться в файл.

Error- Тип 1: Отображение в консоли

subprocess.check_call(bash_str, shell=True)

subprocess.CalledProcessError: Command 'identify -verbose /home/andylu/Desktop/Models_Master/AERSURFACE/Input/Images/Denia_CORINE_CODE_18_reclass_NLCD92_reproj_ADAPTED_Europe_AEA.tif | grep -i "274"' returned non-zero exit status 1.

Тип ошибки 2: Перенаправление вывода в текстовый файл

subprocess.call(bash_str, stdout=filehandle_dummy, stderr=filehandle_dummy

FileNotFoundError: [Errno 2] No such file or directory: 'identify -verbose /home/andylu/Desktop/Models_Master/AERSURFACE/Input/Images/Denia_CORINE_CODE_18_reclass_NLCD92_reproj_ADAPTED_Europe_AEA.tif | grep -i "274"': 'identify -verbose /home/andylu/Desktop/Models_Master/AERSURFACE/Input/Images/Denia_CORINE_CODE_18_reclass_NLCD92_reproj_ADAPTED_Europe_AEA.tif | grep -i "274"'

КОД

Эти subprocess.check_call() функции были выполнены следующая удобная функция:

def subprocess_stdout_to_console_or_file(bash_str, filehandle=None):
    """Function documentation:\n
    Convenience tool which either prints out directly in the provided shell, i.e. console,
    or redirects the output to a given file.

    NOTE on file redirection: it must not be the filepath, but the FILEHANDLE,
    which can be achieved via the open(filepath, "w")-function, e.g. like so:
    filehandle = open('out.txt', 'w')
    print(filehandle): <_io.TextIOWrapper name='bla_dummy.txt' mode='w' encoding='UTF-8'>
    """

    # Check whether a filehandle has been passed or not
    if filehandle is None:
        # i) If not, just direct the output to the BASH (shell), i.e. the console
        subprocess.check_call(bash_str, shell=True)
    else:
        # ii) Otherwise, write to the provided file via its filehandle
        subprocess.check_call(bash_str, stdout=filehandle)

Кусок кода, где все происходит, уже перенаправляет вывод print() в текстовый файл. Вышеупомянутая функция вызывается в функции print_out_all_TIFF_Tags_n_filter_for_desired_TAGs().

Поскольку выходы подпроцесса не перенаправляются автоматически вместе с выходами print(), необходимо передать дескриптор файла в subprocess.check_call(bash_str, stdout=filehandle) через его ключевое слово-аргумент stdout. Тем не менее, вышеупомянутая ошибка также может произойти за пределами этой зоны перенаправления stdout, созданной contextlib.redirect_stdout().

dummy_filename = "/home/andylu/bla_dummy.txt"  # will be saved temporarily in the user's home folder

# NOTE on scope: redirect sys.stdout for python 3.4x according to the following website_
# https://stackoverflow.com/questions/14197009/how-can-i-redirect-print-output-of-a-function-in-python
with open(dummy_filename, 'w') as f:
    with contextlib.redirect_stdout(f):
        print_out_all_TIFF_Tags_n_filter_for_desired_TAGs(
            TIFF_filepath)

OS и Python версиями

  • OS:

    NAME = "Ubuntu" VERSION = "18.04.3 LTS (Bioni c Beaver)" ID = ubuntu ID_LIKE = debian PRETTY_NAME = "Ubuntu 18.04.3 LTS" VERSION_ID = "18.04"

  • Python:

    Python 3.7.6 (по умолчанию, 8 января 2020 г., 19:59:22) [G CC 7.3.0]: : Анаконда, В c. linux

1 Ответ

0 голосов
/ 16 января 2020

Однажды я столкнулся с подобной проблемой, как эта, и это исправило ее.

cmd_str.split(' ')

Мой код:

# >>>>>>>>>>>>>>>>>>>>>>> UNZIP THE FILE AND RETURN THE FILE ARGUMENTS <<<<<<<<<<<<<<<<<<<<<<<<<<<<

def unzipFile(zipFile_):
    # INITIALIZE THE UNZIP COMMAND HERE
    cmd = "unzip -o " + zipFile_ + " -d " + outputDir

    Tlog("UNZIPPING FILE " + zipFile_)

    # GET THE PROCESS OUTPUT AND PIPE IT TO VARIABLE
    log = subprocess.Popen(cmd.split(' '), stdout=subprocess.PIPE, stderr=subprocess.PIPE)

    # GET BOTH THE ERROR LOG AND OUTPUT LOG FOR IT
    stdout, stderr = log.communicate()

    # FORMAT THE OUTPUT
    stdout = stdout.decode('utf-8')
    stderr = stderr.decode('utf-8')

    if stderr != "" :
        Tlog("ERROR WHILE UNZIPPING FILE \n\n\t"+stderr+'\n')
        sys.exit(0)

    # INITIALIZE THE TOTAL UNZIPPED ITEMS
    unzipped_items = []

    # DECODE THE STDOUT TO 'UTF-8' FORMAT AND PARSE LINE BY LINE
    for line in stdout.split('\n'):
        # CHECK IF THE LINE CONTAINS KEYWORD 'inflating'
        if Regex.search(r"inflating",line) is not None:

        # FIND ALL THE MATCHED STRING WITH REGEX
        Matched = Regex.findall(r"inflating: "+outputDir+"(.*)",line)[0]

        # SUBSTITUTE THE OUTPUT BY REMOVING BEGIN/END WHITESPACES
        Matched = Regex.sub('^\s+|\s+$','',Matched)

        # APPEND THE OUTPUTS TO LIST
        unzipped_items.append(outputDir+Matched)

    # RETURN THE OUTPUT
    return unzipped_items
...