Как передать произвольные аргументы в Python - PullRequest
3 голосов
/ 07 ноября 2019

В задании, которое мне нужно сделать, я должен создать альтернативу команде 'rm'. Я должен передать переменное число аргументов, например,

$ rm.py /path/to/some/file ./somefile someotherfile
$ rm.py /path/to/some/file ./somefile someotherfile -r
$ rm.py -r /path/to/some/file ./somefile someotherfile
$ rm.py *.java

аргумент -r может быть передан как любой аргумент, в любом месте. значение -r такое же, как и при использовании обычной команды 'rm'. он рекурсивно удаляет каталог и его содержимое в нем.

он запускает скрипт, и какой бы путь ни указывался, например

rm.py /path/to/some/file

, затем он перемещает его в выходной каталог ~ ~ rm_trashесли есть дубликаты, я тоже об этом беспокоюсь.

Но для начала у меня возникли некоторые проблемы с пониманием того, как к этому подойти. Должен ли я идти об этом в цикле for, и если один из аргументов, равный '-r', идет оттуда?

Должен ли я импортировать и использовать argparse?

У меня есть еще нескольковопросы, но я хотел бы сначала разобраться с тем, что я спрашиваю выше.

При необходимости публиковать снова, все еще не понимаю, как я могу получить конкретный аргумент для любого количества аргументов, кроме 'r'

Ответы [ 4 ]

2 голосов
/ 07 ноября 2019

Я бы использовал argparse, так как вы можете указать действия вне ордера:

https://docs.python.org/3/library/argparse.html

1 голос
/ 07 ноября 2019

Определите функцию синтаксического анализа, которая ищет строку '-r':

def parse(alist, astr='-r'):
    try:
        idx = alist.index(astr)
        r = alist.pop(idx)
        return True, alist
    except ValueError:
        return False, alist

Если мы сделаем

import sys
r, rest = parse(sys.argv[1:])

, то получим значение True / False для rи список имен файлов. Используйте их в остальной части вашего кода.

Тестирование:

In [326]: list1 = 'rm.py /path/to/some/file ./somefile someotherfile'.split()   
In [329]: r, rest = parse(list1[1:])                                            
In [330]: r, rest                                                               
Out[330]: (False, ['/path/to/some/file', './somefile', 'someotherfile'])

In [331]: list2 = 'rm.py /path/to/some/file ./somefile someotherfile -r'.split()                                                                     
In [332]: r, rest = parse(list2[1:])                                            
In [333]: r, rest                                                               
Out[333]: (True, ['/path/to/some/file', './somefile', 'someotherfile'])

Чтобы проиллюстрировать, что происходит, когда присутствует '-r':

In [335]: list2.index('-r')                                                     
Out[335]: 4
In [336]: list2.pop(4)                                                          
Out[336]: '-r'
In [337]: list2                                                                 
Out[337]: ['rm.py', '/path/to/some/file', './somefile', 'someotherfile']

, если это не такПредставляем, мы получаем ValueError:

In [338]: list1.index('-r')                                                     
---------------------------------------------------------------------------
ValueError                                Traceback (most recent call last)
<ipython-input-338-807fbe60be44> in <module>
----> 1 list1.index('-r')

ValueError: '-r' is not in list

======

Эквивалентные функциональные возможности, используя argparse:

In [339]: import argparse                                                       
In [340]: parser = argparse.ArgumentParser()                                    
In [341]: parser.add_argument('-r', action='store_true', help='recursive flag');                                                                       
In [342]: parser.add_argument('rest', nargs='*', help='file names');            
In [343]: args = parser.parse_args(list1[1:])                                   

Использование args = parser.parse_args() для чтения sys.argv.

Результатом является namespace объект, имеющий необходимые атрибуты:

In [344]: args                                                                  
Out[344]: Namespace(r=False, rest=['/path/to/some/file', './somefile', 'someotherfile'])
In [345]: args.r                                                                
Out[345]: False
In [346]: args.rest                                                             
Out[346]: ['/path/to/some/file', './somefile', 'someotherfile']

Используйте args.r и args.rest таким же образомкак r и rest выше.

'-r' может быть до или после списка имен файлов. argparse становится более полезным, когда вы хотите определить больше опций, таких как '-r'. Он также заботится об отображении сообщения справки и значимых ошибок.

In [347]: parser.parse_args(['--help'])                                         
usage: ipython3 [-h] [-r] [rest [rest ...]]

positional arguments:
  rest        file names

optional arguments:
  -h, --help  show this help message and exit
  -r          recursive flag
1 голос
/ 07 ноября 2019

Если вы не хотите использовать argparse или не можете в целях назначения, вы можете заглянуть внутрь sys.argv:

is_recursive = any(arg == '-r' for arg in sys.argv)  

# `paths` will be a list of all other arguments
paths = [arg for arg in sys.argv if arg != '-r']   
0 голосов
/ 07 ноября 2019

Почему бы не использовать:

os.system( 'rm ' + ' '.join( sys.argv[1:] )

и сделать это.

...