Бажаєте запускати ваші Python-скрипти з використанням аргументів командного рядка? Давайте розглянемо, як аналізувати ці аргументи за допомогою модулів `sys`, `getopt` та `argparse` у Python.
У Python для отримання даних від користувача зазвичай використовують функцію `input()`. Проте, в деяких ситуаціях необхідно передавати певні параметри безпосередньо при виконанні скрипту через командний рядок.
У цій статті ми навчимося, як запускати Python-скрипти з різними параметрами та аргументами, введеними через командний рядок. Згодом ми розглянемо, як використовувати вбудовані Python-модулі для обробки цих параметрів і аргументів.
Приступимо!
Розгляд `sys.argv` у Python
Якщо ви знайомі з програмуванням на C, то знаєте, що одним із найпростіших способів передачі аргументів до програми є використання командного рядка. Для цього основна функція може мати таку структуру:
#include<stdio.h> int main(int argc, char **argv){ //argc: лічильник аргументів //argv: вектор аргументів //дії з аргументами return 0; }
Тут `argc` представляє кількість аргументів, а `argv` — вектор аргументів.
Виконання Python-скриптів з аргументами командного рядка
У Python скрипт можна запустити з командного рядка за допомогою команди `python3 filename.py`. Також можна додати будь-яку кількість аргументів командного рядка:
$ python3 filename.py arg1 arg2 ... argn
Модуль `sys` надає вбудовану підтримку для доступу та маніпулювання цими аргументами. `sys.argv` являє собою список всіх аргументів, переданих під час запуску Python-скрипту.
Наприклад, припустимо, що ми запускаємо файл `main.py` з наступними аргументами:
$ python3 main.py hello world python script
Ми можемо ітерувати вектор аргументів, використовуючи цикл `for` та функцію `enumerate`:
# main.py import sys for idx, arg in enumerate(sys.argv): print(f"arg{idx}: {arg}")
# Вивід arg0:main.py arg1:hello arg2:world arg3:python arg4:script
Зверніть увагу, що перший аргумент (з індексом 0) — це назва файлу Python. Наступні аргументи починаються з індексу 1.
Це базова програма, яка здатна приймати та обробляти аргументи командного рядка. Однак, вона має деякі недоліки:
- Як користувачі програми дізнаються, які саме аргументи слід передавати?
- Яке призначення цих аргументів?
Зрозумілість тут низька. Для вирішення цієї проблеми можна використовувати модулі `getopt` або `argparse`, про які ми поговоримо далі. ✅
Аналіз аргументів командного рядка за допомогою `getopt` у Python
Давайте навчимося обробляти аргументи командного рядка з використанням вбудованого модуля `getopt`.
Після імпортування `getopt` з модуля `getopt`, необхідно вказати аргументи для аналізу, а також короткі та довгі параметри для запуску скрипту. Нам потрібно обробити всі аргументи, починаючи з індексу 1 в `sys.argv`, тобто фрагмент для аналізу – `sys.argv[1:]`.
Припустимо, що програма очікує рядок повідомлення та ім’я файлу. Ми будемо використовувати `m` та `f` як короткі варіанти, а `message` та `file` як довгі.
Але як ми гарантуємо, що певний параметр потребує аргумент?
- У коротких параметрах можна зробити так, щоб параметр вимагав аргументу, додавши двокрапку (`:`) після короткої назви параметра.
- Аналогічно, у довгих параметрах можна додати знак `=` після довгого параметра. Ці параметри та їх відповідні аргументи можна буде зафіксувати.
Застосувавши це, отримаємо наступний код у `main.py`:
# main.py import sys from getopt import getopt opts, args = getopt(sys.argv[1:],'m:f:',['message=','file=']) print(opts) print(args)
Тут змінна `opts` містить параметри та аргументи у вигляді списку кортежів. Всі інші позиційні аргументи збираються у змінну `args`.
Ми можемо передати повідомлення та назву файлу, запускаючи скрипт, використовуючи або короткі, або довгі параметри.
Якщо запустимо `main.py` з довгими параметрами, отримаємо:
$ python3 main.py --message hello --file somefile.txt
В змінній `opts` будуть параметри та аргументи у вигляді кортежів. Оскільки позиційні аргументи не були передані, `args` буде порожнім списком.
# Вивід [('--message', 'hello'), ('--file', 'somefile.txt')] []
Аналогічно, можна використовувати короткі варіанти, як показано нижче:
$ python3 main.py -m hello -f somefile.txt
# Вивід [('-m', 'hello'), ('-f', 'somefile.txt')] []
⚠️ Важливо: Короткий параметр `-m` в даному прикладі не слід плутати з прапорцем командного рядка `-m`, який використовується для запуску модуля як основного при виконанні Python-скрипту.
Наприклад, команда `python3 -m unittest main.py` використовує `unittest` як основний модуль під час запуску `main.py`.
Як згадувалось раніше, всі інші позиційні аргументи будуть зібрані в змінній `args`. Ось приклад:
$ python3 main.py -m hello -f somefile.txt another_argument
Список аргументів містить позиційний аргумент `another_argument`.
# Вивід [('-m', 'hello'), ('-f', 'somefile.txt')] ['another_argument']
Оскільки `opts` є списком кортежів, ми можемо пройтися по ньому, розпакувати кортеж та отримати аргументи, що відповідають певним параметрам.
Але що нам робити з назвою файлу та повідомленням після обробки аргументів? Ми відкриємо файл в режимі запису і запишемо туди повідомлення у верхньому регістрі.
# main.py import sys from getopt import getopt opts, args = getopt(sys.argv[1:],'m:f:',['message=','file=']) print(opts) print(args) for option, argument in opts: if option == '-m': message = argument if option == '-f': file = argument with open(file,'w') as f: f.write(message.upper())
Запустимо `main.py` з короткими параметрами та аргументами командного рядка:
$ python main.py -m hello -f thisfile.txt [('-m', 'hello'), ('-f', 'thisfile.txt')] []
Після запуску `main.py` в робочому каталозі з’явиться файл `thisfile.txt`, що містить рядок “hello”, переведений у верхній регістр (“HELLO”).
$ ls main.py thisfile.txt
$ cat thisfile.txt HELLO
Аналіз аргументів командного рядка з використанням `argparse`
Модуль `argparse`, також входить до стандартної бібліотеки Python, забезпечує функціональність для обробки аргументів командного рядка та створення інтерфейсів командного рядка.
Для аналізу аргументів командного рядка імпортуємо клас `ArgumentParser` з модуля `argparse`. Створюємо екземпляр `arg_parser`, об’єкт класу `ArgumentParser`:
from argparse import ArgumentParser arg_parser = ArgumentParser()
Далі нам потрібно додати два аргументи командного рядка:
- `message`: рядок повідомлення;
- `file`: назва файлу для роботи.
Викличемо метод `add_argument()` на `arg_parser` для додавання обох аргументів. У виклику методу `add_argument()` можна задати `help` (опис аргументу).
arg_parser.add_argument('message',help='рядок повідомлення') arg_parser.add_argument('file',help='назва файлу')
Тепер у нас є екземпляр `arg_parser` і додано аргументи командного рядка. При запуску програми в командному рядку можна використовувати метод `parse_args()` на `arg_parser`, щоб отримати значення аргументів.
Тут простір імен аргументів зберігається в змінній `args`. Отже, можна використовувати `args.argument_name`, щоб отримати значення конкретного аргументу.
Отримавши значення аргументів, запишемо рядок повідомлення зі зміною регістру літер (за допомогою методу `swapcase()`) у файл.
args = arg_parser.parse_args() message = args.message file = args.file with open(file,'w') as f: f.write(message.swapcase())
З’єднавши все разом, отримаємо наступний файл `main.py`:
# main.py from argparse import ArgumentParser arg_parser = ArgumentParser() arg_parser.add_argument('message',help='рядок повідомлення') arg_parser.add_argument('file',help='назва файлу') args = arg_parser.parse_args() print(args) message = args.message file = args.file with open(file,'w') as f: f.write(message.swapcase())
Розуміння використання аргументів командного рядка
Для розуміння використання аргументів при запуску `main.py`, можна скористатися довгим параметром `–help`, як показано нижче:
$ python3 main.py --help usage: main.py [-h] message file positional arguments: message рядок повідомлення file назва файлу optional arguments: -h, --help показує довідку та виходить
Тут немає додаткових аргументів, і `message` та `file` – обов’язкові позиційні аргументи. Також можна використовувати коротку опцію `-h`:
$ python3 main.py -h usage: main.py [-h] message file positional arguments: message рядок повідомлення file назва файлу optional arguments: -h, --help показує довідку та виходить
Як бачимо, обидва аргументи за замовчуванням є позиційними. Якщо не передати один або декілька з цих аргументів, виникне помилка.
Тут ми передали позиційний аргумент (“Hello”) для рядка повідомлення, але не вказали значення для аргументу `file`.
В результаті виникає помилка про відсутність аргументу `file`.
$ python3 main.py Hello usage: main.py [-h] message file main.py: error: потрібні наступні аргументи: file
Якщо запустити `main.py` з обома позиційними аргументами, то побачимо, що простір імен `args` містить значення аргументів.
$ python3 main.py Hello file1.txt
# Вивід Namespace(file='file1.txt', message='Hello')
Перевіривши вміст поточного робочого каталогу, побачимо, що скрипт створив файл `file1.txt`:
$ ls file1.txt main.py
Початковий рядок повідомлення: “Hello”; після заміни регістру літер рядок в файлі `file1.txt` виглядає як `hELLO`.
$ cat file1.txt hELLO
Як зробити аргументи командного рядка необов’язковими
Щоб зробити ці аргументи командного рядка необов’язковими, можна додати префікс `–` до їхніх назв.
Змінимо `main.py` таким чином, щоб аргументи `message` та `file` стали необов’язковими.
# main.py from argparse import ArgumentParser arg_parser = ArgumentParser() arg_parser.add_argument('--message',help='рядок повідомлення') arg_parser.add_argument('--file',help='назва файлу')
Оскільки аргументи командного рядка є необов’язковими, можна встановити значення за замовчуванням для них.
if args.message and args.file: message = args.message file = args.file else: message="Python3" file="myfile.txt"
На цьому етапі, файл `main.py` має такий вигляд:
# main.py from argparse import ArgumentParser arg_parser = ArgumentParser() arg_parser.add_argument('--message',help='рядок повідомлення') arg_parser.add_argument('--file',help='назва файлу') args = arg_parser.parse_args() print(args) if args.message and args.file: message = args.message file = args.file else: message="Python3" file="myfile.txt" with open(file,'w') as f: f.write(message.swapcase())
Перевіривши використання, побачимо, що і `message`, і `file` тепер необов’язкові. Це означає, що можна запускати `main.py` взагалі без цих аргументів.
$ python3 main.py --help usage: main.py [-h] [--message MESSAGE] [--file FILE] optional arguments: -h, --help показує довідку та виходить --message MESSAGE рядок повідомлення --file FILE назва файлу
$ python3 main.py
У просторі імен аргументів `file` та `message` мають значення `None`.
# Вивід Namespace(file=None, message=None)
Як бачимо, використовуються назва файлу та повідомлення за замовчуванням: `myfile.txt` та `Python3`. Файл `myfile.txt` з’являється в робочому каталозі:
$ ls file1.txt main.py myfile.txt
Він містить рядок “Python3” зі зміною регістру літер:
$ cat myfile.txt pYTHON3
Також можна використовувати аргументи `–message` та `–file`, щоб зробити команду більш читабельною.
$ python3 main.py --message Coding --file file2.txt
# Вивід Namespace(file='file2.txt', message='Coding')
В робочому каталозі з’являється `file2.txt`:
$ ls file1.txt file2.txt main.py myfile.txt
Він містить рядок “CODING”, як і очікувалося.
$ cat file2.txt cODING
Висновок
Підсумуємо, що ми дізналися у цьому посібнику:
- Як і в мові програмування C, у Python можна отримати доступ до аргументів командного рядка, перебираючи вектор аргументів `sys.argv`. `sys.argv[0]` є назвою Python-скрипту. Отже, нас цікавить аналіз аргументів `sys.argv[1:]`.
- Для підвищення читабельності та можливості додавання параметрів можна використовувати модулі `getopt` та `argparse`.
- Модуль `getopt` використовується для аналізу списку аргументів командного рядка, починаючи з індексу 1 і до кінця списку. Можна вказувати як короткі, так і довгі варіанти параметрів.
- Коли параметр приймає аргумент, слід додати двокрапку (`:`) та знак `=` після короткого та довгого параметрів відповідно.
- Модуль `argparse` дозволяє створити екземпляр об’єкта `ArgumentParser` та використовувати метод `add_argument()` для додавання потрібного позиційного аргументу. Щоб зробити аргумент необов’язковим, потрібно додати перед його назвою `–`.
- Для отримання значень аргументів командного рядка потрібно викликати метод `parse_args()` об’єкта `ArgumentParser`.
Далі ви можете ознайомитися з безпечним хешуванням у Python.