parse_args все.png файлы из аргумента парсера

Я хотел бы получить arg.pics который возвращает что-то вроде ['pic1.png', 'pic2.png', 'pic3.png'] (для произвольного разбора всех файлов формата.png) после запуска следующего (test.py):

import argparse
import os

def parser_arg():
    par = argparse.ArgumentParser()
    parser = par.add_argument_group('pictures')
    parser.add_argument("-p", "--pics", nargs="+", help="picture files", required=True)
    arguments = par.parse_args()
    return arguments

args = parser_arg()

И после запуска сценария через командную строку и ввода

python test.py -p ../User/Desktop/Data/*.png

затем args.pics возвращается ['../User/Desktop/Data/*.png'] вместо..

Я использую правильный подход? Я слышал, используя *.png будет введен в файлы.png после ввода, но с моей стороны это не так.

Редактирует: я использую Anaconda Prompt на Windows 10, если это помогает.

2 ответа

Решение

Есть несколько вещей, которые могут происходить. Одна возможность состоит в том, что ../User/Desktop/Data/*.png не соответствует ни одному файлу, поэтому не расширяется. Это может произойти только в UNIX-подобной оболочке (или, я полагаю, в PowerShell). Другая возможность заключается в том, что вы используете cmd.exe на Windows, которая просто не делает подстановочные знаки вообще. Учитывая, что вы используете приглашение Anaconda в Windows, я бы предпочел в качестве объяснения последнюю возможность.

Так как вы ищете список всех PNG в папке, вам вообще не нужно полагаться на оболочку. Есть много способов сделать то же самое в Python, с интеграцией и без argparse,

Давайте начнем с реализации функции листинга. Для данного каталога есть несколько способов получить список всех PNG в нем:

  1. использование glob.glob (рекомендуемый вариант). Это может либо переходить в подкаталоги, либо нет, в зависимости от того, что вы хотите:

    mydir = '../User/Desktop/Data/'
    pngs = glob.glob(os.path.join(mydir, '*.png'))
    

    Чтобы перейти в подпапки, просто добавьте recursive=True опция только для ключевых слов.

  2. использование os.walk, Это гораздо более гибко (и, следовательно, требует больше работы), но также позволяет иметь рекурсивные или нерекурсивные решения:

    mydir = '../User/Desktop/Data/'
    pngs = []
    for path, dirs, files in os.walk(mydir):
        pngs.extend(f for f in files if f.lower().endswith('.png'))
        del dirs[:]
    

    Чтобы включить рекурсию, просто удалите строку del dirs[:], который подавляет поиск в подкаталогах.

  3. Связанный метод, который всегда является нерекурсивным, заключается в использовании os.listdir, который является грубым эквивалентом питонов ls или же dir команды:

    mydir = '../User/Desktop/Data/'
    pngs = [f for f in os.listdir(mydir) if f.lower().endswith('.png')]
    

    Эта версия не проверяет, является ли что-то файлом. Предполагается, что у вас нет имен папок, оканчивающихся на .png,

Допустим, вы выбрали один из этих методов и создали функцию, которая принимает папку и возвращает список файлов:

def list_pngs(directory):
    return glob.glob(os.path.join(directory, '*.png'))

Теперь, когда вы знаете, как перечислять файлы в папке, вы можете легко подключить это к argparse на любом уровне. Вот пара примеров:

  1. Просто получите все ваши каталоги из аргумента и перечислите их потом:

    parser.add_argument("-p", "--pics", action='store', help="picture files", required=True)
    

    Как только вы обработали аргументы:

    print(list_pngs(args.pics))
    
  2. Интегрировать непосредственно в argparse с type аргумент:

    parser.add_argument("-p", "--pics", action='store', type=list_pngs, help="picture files", required=True)
    

    Теперь вы можете использовать аргумент напрямую, так как он будет напрямую преобразован в список:

    print(args.pics)
    

Ваш подход правильный. Тем не менее, ваш сценарий будет получать расширенный список файлов в качестве параметров, только если ваша оболочка поддерживает глобирование и шаблон фактически соответствует любым файлам. В противном случае это будет сам шаблон в большинстве случаев.

Командная строка Anaconda использует cmd.exe по умолчанию, который не поддерживает расширение по шаблону. Вместо этого вы можете использовать PowerShell, который понимает подстановочные знаки. Кроме того, вы можете выполнить расширение в своем приложении, как описано в ответе Mad Physicist.

Другие вопросы по тегам