Как разобрать неузнаваемый аргумент?

#python #python-3.x #argparse

#python #python-3.x #argparse

Вопрос:

для моей программы мне нужно разобрать один файл .xml и один файл .ttf. Я не хочу беспокоить пользователя, вводя идентификатор аргумента, но я бы предпочел принять проанализированные данные, а затем решить, какой файл какой на основе .extension . Возможно ли с помощью argparser сделать что-то вроде

 py -3 file.py "C/documents/file.xml" "C/documents/font.ttf"
  

в неизвестном порядке и решить после получения путей к файлам? Мне просто нужно знать, как преобразовать такую информацию в программу Python, не прерывая ее. Спасибо

Комментарии:

1. О чем вы здесь спрашиваете? О каком «прерывании» вы говорите? Вы можете сделать if param.endswith('xml') , например.

2. Другим вариантом может быть просто повторение sys.argv и проверка с помощью .endswith('.xml')

Ответ №1:

После получения входных данных от пользователя, предполагая, что их пути находятся в var1 и var2 , просто проверьте расширения, используя var1.split(".")[1] и var2.split(".")[1] (они возвращают строку после точки, которая является вашим расширением файла) и сделайте что-то вроде этого (предполагая, что пользователь не поместил два файла с одинаковым расширением)

 if var1.split(".")[1] == "xml"
 xml_file=var1
 ttf_file=var2
else:
 xml_file=var2
 ttf_file=var1
  

Комментарии:

1. Я хотел знать, как его разобрать. Я не понимаю комментарий Дэниела Роземана, но Ральф любезно указал, что это можно сделать с помощью sys.argv, я был сосредоточен на поиске решения, связанного с argparse, но я не знаю, как это сделать с помощью этого модуля

2. Я бы рекомендовал для вашего кода использовать split(‘.’)[-1], вы не можете знать, сколько точек может быть в пути. Который совпадает с endswith. Если путь является C/master.on.xml/documents/file.xml тогда у вас проблема

Ответ №2:

Благодаря Ralf в комментариях под моим вопросом я пришел к решению

 args = sys.argv[1:] #the first one is path of your python script
if len(args) > 3:
    print('wrong')

for i in args:
    if i.endswith('.xml'):
        xml_path = i
    if i.endswith('.ttf'):
        font_path = i
  

Комментарии:

1. Обратите внимание, что если вы передадите более одного XML-имени, последнее выиграет, а остальные будут молча проигнорированы. Это легко исправить с помощью проверки на xml_path is None перед назначением и сигнализировать об ошибке.

2. вы правы, спасибо. Я думал, что это можно было бы решить с помощью len (args), но two .xml может быть проанализирован, и он также пройдет через него.

Ответ №3:

Вы можете использовать пользовательское действие. Вызов delattr кажется мне немного сомнительным, но сохраняет пространство имен чистым.

 class InputFileAction(argparse.Action):
    def __call__(self, parser, namespace, values, option_string=None):
        if values.endswith(".ttf"):
            dest = "ttf_file"
        elif values.endswith(".xml"):
            dest = "xml_file"
        else:
            raise argparse.ArgumentTypeError("File must have .ttf or .xml extension")

        setattr(namespace, dest, values)
        delattr(namespace, self.dest)


p = argparse.ArgumentParser()
p.add_argument("input1", action=InputFileAction)
p.add_argument("input2", action=InputFileAction)
  

Несколько примеров:

 >>> p.parse_args(["foo.ttf", "foo.xml"])
Namespace(ttf_file='foo.ttf', xml_file='foo.xml')
>>> p.parse_args(["foo.xml", "foo.ttf"])
Namespace(ttf_file='foo.ttf', xml_file='foo.xml')