Windows запуск python скрипта с параметрами

This is my python hello.py script: def hello(a,b): print "hello and that's your sum:" sum=a+b print sum import sys if __name__ == "__main__": hello(sys.argv[2]) The problem i...

This is my python hello.py script:

def hello(a,b):
    print "hello and that's your sum:"
    sum=a+b
    print sum
    import sys

if __name__ == "__main__":
    hello(sys.argv[2])

The problem is that it can’t be run from the windows command line prompt, I used this command:

C:Python27>hello 1 1

But it didn’t work unfortunately, may somebody please help?

falsetru's user avatar

falsetru

349k62 gold badges703 silver badges622 bronze badges

asked Jul 9, 2013 at 9:11

user2563817's user avatar

2

  • import sys out of hello function.
  • arguments should be converted to int.
  • String literal that contain ' should be escaped or should be surrouned by ".
  • Did you invoke the program with python hello.py <some-number> <some-number> in command line?

import sys

def hello(a,b):
    print "hello and that's your sum:", a + b

if __name__ == "__main__":
    a = int(sys.argv[1])
    b = int(sys.argv[2])
    hello(a, b)

answered Jul 9, 2013 at 9:18

falsetru's user avatar

falsetrufalsetru

349k62 gold badges703 silver badges622 bronze badges

9

I found this thread looking for information about dealing with parameters; this easy guide was so cool:

import argparse

parser = argparse.ArgumentParser(description='Script so useful.')
parser.add_argument("--opt1", type=int, default=1)
parser.add_argument("--opt2")

args = parser.parse_args()

opt1_value = args.opt1
opt2_value = args.opt2

runs like:

python myScript.py --opt2 = 'hi'

answered Feb 11, 2020 at 19:40

hestellezg's user avatar

hestellezghestellezg

3,0493 gold badges31 silver badges34 bronze badges

1

Here are all of the previous answers summarized:

  • modules should be imported outside of functions.
  • hello(sys.argv[2]) needs to be indented since it is inside an if statement.
  • hello has 2 arguments so you need to call 2 arguments.
  • as far as calling the function from terminal, you need to call python .py …

The code should look like this:

import sys
def hello(a, b):
    print "hello and that's your sum:"
    sum = a+b
    print sum

if __name__== "__main__":
    hello(int(sys.argv[1]), int(sys.argv[2]))

Then run the code with this command:

python hello.py 1 1

Charles's user avatar

Charles

9171 gold badge15 silver badges39 bronze badges

answered Jul 3, 2017 at 19:17

C. Glass's user avatar

C. GlassC. Glass

1811 silver badge3 bronze badges

To execute your program from the command line, you have to call the python interpreter, like this :

C:Python27>python hello.py 1 1

If you code resides in another directory, you will have to set the python binary path in your PATH environment variable, to be able to run it, too. You can find detailed instructions here.

Community's user avatar

answered Jul 9, 2013 at 9:14

thibauts's user avatar

thibautsthibauts

1,6289 silver badges8 bronze badges

3

Your indentation is broken. This should fix it:

import sys

def hello(a,b):
    print 'hello and thats your sum:'
    sum=a+b
    print sum

if __name__ == "__main__":
    hello(sys.argv[1], sys.argv[2])

Obviously, if you put the if __name__ statement inside the function, it will only ever be evaluated if you run that function. The problem is: the point of said statement is to run the function in the first place.

answered Jul 9, 2013 at 9:16

Nils Werner's user avatar

Nils WernerNils Werner

33.8k7 gold badges74 silver badges97 bronze badges

1

import sys

def hello(a, b):
    print  'hello and that's your sum: {0}'.format(a + b)

if __name__ == '__main__':
    hello(int(sys.argv[1]), int(sys.argv[2]))

Moreover see @thibauts answer about how to call python script.

answered Jul 9, 2013 at 9:19

ElmoVanKielmo's user avatar

ElmoVanKielmoElmoVanKielmo

10.6k2 gold badges31 silver badges45 bronze badges

There are more than a couple of mistakes in the code.

  1. ‘import sys’ line should be outside the functions as the function is itself being called using arguments fetched using sys functions.
  2. If you want correct sum, you should cast the arguments (strings) into floats. Change the sum line to —> sum = float(a) + float(b).
  3. Since you have not defined any default values for any of the function arguments, it is necessary to pass both arguments while calling the function —> hello(sys.argv[2], sys.argv[2])

    import sys
    def hello(a,b):
    print ("hello and that's your sum:")
    sum=float(a)+float(b)
    print (sum)

    if __name__ == "__main__":
    hello(sys.argv[1], sys.argv[2])

Also, using «C:Python27>hello 1 1» to run the code looks fine but you have to make sure that the file is in one of the directories that Python knows about (PATH env variable). So, please use the full path to validate the code.
Something like:

C:Python34>python C:UserspranaykDesktophello.py 1 1

answered Nov 29, 2019 at 11:20

Pranay Kumar's user avatar

This is my python hello.py script:

def hello(a,b):
    print "hello and that's your sum:"
    sum=a+b
    print sum
    import sys

if __name__ == "__main__":
    hello(sys.argv[2])

The problem is that it can’t be run from the windows command line prompt, I used this command:

C:Python27>hello 1 1

But it didn’t work unfortunately, may somebody please help?

falsetru's user avatar

falsetru

349k62 gold badges703 silver badges622 bronze badges

asked Jul 9, 2013 at 9:11

user2563817's user avatar

2

  • import sys out of hello function.
  • arguments should be converted to int.
  • String literal that contain ' should be escaped or should be surrouned by ".
  • Did you invoke the program with python hello.py <some-number> <some-number> in command line?

import sys

def hello(a,b):
    print "hello and that's your sum:", a + b

if __name__ == "__main__":
    a = int(sys.argv[1])
    b = int(sys.argv[2])
    hello(a, b)

answered Jul 9, 2013 at 9:18

falsetru's user avatar

falsetrufalsetru

349k62 gold badges703 silver badges622 bronze badges

9

I found this thread looking for information about dealing with parameters; this easy guide was so cool:

import argparse

parser = argparse.ArgumentParser(description='Script so useful.')
parser.add_argument("--opt1", type=int, default=1)
parser.add_argument("--opt2")

args = parser.parse_args()

opt1_value = args.opt1
opt2_value = args.opt2

runs like:

python myScript.py --opt2 = 'hi'

answered Feb 11, 2020 at 19:40

hestellezg's user avatar

hestellezghestellezg

3,0493 gold badges31 silver badges34 bronze badges

1

Here are all of the previous answers summarized:

  • modules should be imported outside of functions.
  • hello(sys.argv[2]) needs to be indented since it is inside an if statement.
  • hello has 2 arguments so you need to call 2 arguments.
  • as far as calling the function from terminal, you need to call python .py …

The code should look like this:

import sys
def hello(a, b):
    print "hello and that's your sum:"
    sum = a+b
    print sum

if __name__== "__main__":
    hello(int(sys.argv[1]), int(sys.argv[2]))

Then run the code with this command:

python hello.py 1 1

Charles's user avatar

Charles

9171 gold badge15 silver badges39 bronze badges

answered Jul 3, 2017 at 19:17

C. Glass's user avatar

C. GlassC. Glass

1811 silver badge3 bronze badges

To execute your program from the command line, you have to call the python interpreter, like this :

C:Python27>python hello.py 1 1

If you code resides in another directory, you will have to set the python binary path in your PATH environment variable, to be able to run it, too. You can find detailed instructions here.

Community's user avatar

answered Jul 9, 2013 at 9:14

thibauts's user avatar

thibautsthibauts

1,6289 silver badges8 bronze badges

3

Your indentation is broken. This should fix it:

import sys

def hello(a,b):
    print 'hello and thats your sum:'
    sum=a+b
    print sum

if __name__ == "__main__":
    hello(sys.argv[1], sys.argv[2])

Obviously, if you put the if __name__ statement inside the function, it will only ever be evaluated if you run that function. The problem is: the point of said statement is to run the function in the first place.

answered Jul 9, 2013 at 9:16

Nils Werner's user avatar

Nils WernerNils Werner

33.8k7 gold badges74 silver badges97 bronze badges

1

import sys

def hello(a, b):
    print  'hello and that's your sum: {0}'.format(a + b)

if __name__ == '__main__':
    hello(int(sys.argv[1]), int(sys.argv[2]))

Moreover see @thibauts answer about how to call python script.

answered Jul 9, 2013 at 9:19

ElmoVanKielmo's user avatar

ElmoVanKielmoElmoVanKielmo

10.6k2 gold badges31 silver badges45 bronze badges

There are more than a couple of mistakes in the code.

  1. ‘import sys’ line should be outside the functions as the function is itself being called using arguments fetched using sys functions.
  2. If you want correct sum, you should cast the arguments (strings) into floats. Change the sum line to —> sum = float(a) + float(b).
  3. Since you have not defined any default values for any of the function arguments, it is necessary to pass both arguments while calling the function —> hello(sys.argv[2], sys.argv[2])

    import sys
    def hello(a,b):
    print ("hello and that's your sum:")
    sum=float(a)+float(b)
    print (sum)

    if __name__ == "__main__":
    hello(sys.argv[1], sys.argv[2])

Also, using «C:Python27>hello 1 1» to run the code looks fine but you have to make sure that the file is in one of the directories that Python knows about (PATH env variable). So, please use the full path to validate the code.
Something like:

C:Python34>python C:UserspranaykDesktophello.py 1 1

answered Nov 29, 2019 at 11:20

Pranay Kumar's user avatar

Командная строка Python, параметры и опции.

Схемы командной строки и ее параметров других реализаций могут отличаться. Смотрите альтернативные реализации языка Python для уточнения параметров запуска конкретной реализации.

При вызове Python можно указать любой из следующих параметров:

$ python [-bBdEhiIOqsSuvVWx?] [-c command | -m module-name | script | - ] [args]

Напишем и сохраним в файл test.py небольшую программку, которую будем запускать разными способами.

#!/usr/bin/env python3

def hello(text):
    print(f'Функция "{text}"')

print('Привет Мир')

if __name__ == '__main__':
    hello('hello')

Самым распространенным вариантом использования, конечно, является простой вызов скрипта:

$ python3 test.py
# Привет Мир
# Функция "hello"

Содержание:

  • Перенаправление вывода программы;
  • Запуск скрипта как модуля с параметром -m;
  • Запуск скрипта в интерактивном режиме с параметром -i;
  • Использование имени файла скрипта;
  • Запуск скрипта при выполнении импорта;
  • Использование модуля importlib;
  • Использование модуля runpy;
  • Использование функции exec().

Перенаправление вывода программы.

Иногда бывает полезно сохранить вывод скрипта для последующего анализа. Вот как это сделать:

$ python3 test.py > output.txt

Эта операция сохраняет вывод скрипта в файл output.txt, а не в стандартный системный вывод stdout. В результате на экран попадёт только поток ошибок stderr (в случае их появления). Этот процесс широко известен как перенаправление потока и доступен как в Windows, так и в Unix-подобных системах. Если output.txt не существует, он создается автоматически, если файл уже существует, то его содержимое будет заменено новым выводом.

Что-бы накапливать/добавлять вывод последовательных исполнений скрипта в конец файла output.txt, то нужно использовать две угловые скобки >> вместо одной:

$ python3 test.py >> output.txt

Ну и наконец перенаправление в файл только вывода ошибок (в случае их появления). Для этого достаточно перенаправить стандартный поток ошибок, используя команду 2> (2 — это дескриптор стандартного потока ошибок). В результате на экран попадёт только то, что команда отправляет в стандартный вывод:

$ python3 test.py 2> error.txt

Если необходимо перенаправить в файл вывод всего того, что появляется в консоли при выполнения скрипта (stdout и stderr), и при этом накапливать вывод в файле, то запуск сценария должен выглядеть следующим образом:

$ python3 test.py >> output.log 2>&1
# или проще
$ python3 test.py &>> output.log

Как быть, если нужно сохранить результаты работы сценария Python в отдельный файл, не смешивая данные со сведениями об ошибках? Так как потоки можно перенаправлять независимо друг от друга, то можно добавить в команду запуска сценария перенаправления стандартного потока вывода в один файл, а ошибок в другой файл:

$ python3 test.py > output.txt 2> error.txt
# с добавлением результатов сценария 
# в `output.txt` и перезаписью `error.txt`
$ python3 test.py >> output.txt 2> error.txt

Запуск скрипта как модуля с параметром -m.

Python предлагает ряд параметров командной строки, которые можно использовать в соответствии со своими потребностями. Например, если нужно запустить модуль Python, то необходимо использовать команду python -m <имя-модуля>.

Опция -m ищет в sys.path имя модуля и запускает его содержимое как __main__:

$ python3 -m test
# Привет Мир
# Функция "hello"
Примечание

: имя модуля должно быть именем объекта модуля, а не просто строкой.

Запуск скрипта в интерактивном режиме с параметром -i.

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

$ python3 -i test.py
# Привет Мир
# Функция "hello"

# здесь можно запустить любую 
# функцию с другими аргументами
>>> hello('печатает слово Привет!')
# Функция "печатает слово Привет!"

Использование имени файла скрипта

В последних версиях Windows можно запускать сценарии Python, просто введя имя файла, содержащего код, в командной строке:

C:> test.py
# Привет Мир
# Функция "hello"

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

В Unix-подобных системах, таких как GNU/Linux, можно добиться такого поведения добавив первую строку с текстом #!/usr/bin/env python3. Для Python это простой комментарий, а для операционной системы эта строка указывает, какую программу необходимо использовать для запуска файла.

Эта строка начинается с комбинация символов #!, которая обычно называется «хеш-банг» или «шебанг«, и указывает путь к интерпретатору.

Есть два способа указать путь к интерпретатору:

  • абсолютный путь к интерпретатору: #!/usr/bin/python3.
  • использование команды env операционной системы, которая находит и запускает Python путем поиска в переменной окружения PATH: #!/usr/bin/env python3.

И наконец, чтобы выполнить скрипт в Linux, необходимо назначить ему права на выполнение.

Вот пример того, как это сделать:

# Даем права на выполнение
$ chmod +x test.py
# Запускаем скрипт, используя его имя файла
$ ./test.py
# Привет Мир
# Функция "hello"
Обратите внимание

, что если скрипт не находится в текущем рабочем каталоге, то необходимо указать путь к файлу скрипта, чтобы он запустился.

Запуска скриптов из интерактивного сеанса.

Также можно запускать сценарии и модули Python из интерактивного сеанса. Этот вариант предлагает множество возможностей.

Запуск скрипта при выполнении импорта.

В момент импорта модуля происходит загрузка его содержимого для последующего доступа и использования. Самое интересное в этом процессе то, что на последнем этапе import запускает код.

Когда модуль содержит только определения классов, функций, переменных и констант, то не будет видно, что код действительно выполнялся, но когда модуль включает в себя вызовы функций, методов или других инструкций, которые генерируют видимые результаты и расположенные вне сценария верхнего уровня '__main__', тогда станете свидетелем его исполнения.

>>> import test
# Привет Мир

# вызов функции `hello()`
>>> test.hello('запускается как test.hello()')
# Функция "запускается как test.hello()"

# выполним импорт только функции `hello()`
>>> from test import hello
>>> hello('запускается как hello()')
# Функция "запускается как hello()"

Необходимо отметить, что код, который выполняется вне сценария верхнего уровня '__main__' — работает только один раз за сеанс. После первого импорта последующие импорты ничего не делают, даже если изменить содержимое модуля. Это связано с тем, что операции импорта являются дорогостоящими и поэтому выполняются только один раз.

Использование модуля importlib.

Стандартная библиотеке Python содержит модуль importlib, который предоставляет функцию importlib.reload(). С помощью этой функции можно заставить интерпретатор повторно импортировать модуль и, следовательно, выполнить код модуля заново.

Обратите внимание

, что аргумент importlib.reload() должен быть именем объекта модуля, а не строкой!

# пробуем импортировать еще раз
import test 
# ничего не происходит
>>> import importlib
>>> importlib.reload(test)
# Привет Мир
# <module 'test' from '/home/lyzlov/test.py'>

Функция importlib.reload() также будет полезна, если вы отредактировали исходный файл модуля с помощью внешнего редактора и хотите опробовать новую версию, не выходя из интерпретатора Python.

Использование модуля runpy.

Стандартная библиотека включает модуль runpy, которая имеет функцию runpy.run_module(), позволяющая запускать модули без их предварительного импорта. Эта функция возвращает словарь глобальных переменных исполняемого модуля.

>>> import runpy
>>> runpy.run_module(mod_name='test')
# Привет Мир
# {'__name__': 'test', '__file__': ...
#     ... вывод сокращен ...
# 'hello': <function hello at 0x7f3cdfea65e0>}

Запускаемый модуль ищется с использованием стандартного механизма импорта, а затем выполняется в новом пространстве имен модулей. Первым аргументом runpy.run_module() должна быть строка с абсолютным именем выполняемого модуля без расширения .py.

Модуль runpy также предоставляет функцию runpy.run_path(), которая позволит запустить модуль, указав его расположение в файловой системе:

>>> import runpy
>>> runpy.run_path(path_name='test.py')
# Привет Мир
# {'__name__': 'test', '__file__': ...
#     ... вывод сокращен ...
# 'hello': <function hello at 0x7f3cdfea65e0>}

Как и runpy.run_module(), так и runpy.run_path() возвращает глобальный словарь исполняемого модуля.

Аргумент path_name должен быть строкой и может ссылаться на следующее:

  • Расположение исходного файла Python
  • Расположение скомпилированного файла байт-кода
  • Значение допустимой записи в sys.path, содержащей модуль __main__ (файл __main__.py)

Использование функции exec() .

Встроенная функция exec() поддерживает динамическое выполнение кода Python, тем самым предоставляет альтернативный способ запуска скриптов:

exec(open('test.py').read())
# Привет Мир
# Функция "hello"

Здесь функция open() открывает файл test.py, считывает его содержимое и отправляет в функцию exec(), которая, в свою очередь, запускает код.

Приведенный выше пример немного не соответствует действительности. Это просто «ХАК«, который показывает, насколько может быть Python универсальным и гибким.

I would like to run a command in Python Shell to execute a file with an argument.

For example: execfile("abc.py") but how to add 2 arguments?

Trilarion's user avatar

Trilarion

10.4k9 gold badges64 silver badges102 bronze badges

asked Apr 26, 2011 at 10:18

olidev's user avatar

2

Actually, wouldn’t we want to do this?

import sys
sys.argv = ['abc.py','arg1', 'arg2']
execfile('abc.py')

answered Sep 7, 2013 at 16:29

user2757262's user avatar

user2757262user2757262

5994 silver badges2 bronze badges

3

execfile runs a Python file, but by loading it, not as a script. You can only pass in variable bindings, not arguments.

If you want to run a program from within Python, use subprocess.call. E.g.

import subprocess
subprocess.call(['./abc.py', arg1, arg2])

thlik's user avatar

thlik

3905 silver badges12 bronze badges

answered Apr 26, 2011 at 10:22

Fred Foo's user avatar

Fred FooFred Foo

350k75 gold badges730 silver badges828 bronze badges

4

try this:

import sys
sys.argv = ['arg1', 'arg2']
execfile('abc.py')

Note that when abc.py finishes, control will be returned to the calling program. Note too that abc.py can call quit() if indeed finished.

Jules's user avatar

Jules

14k13 gold badges54 silver badges99 bronze badges

answered Feb 15, 2013 at 23:30

buggywhip's user avatar

buggywhipbuggywhip

6945 silver badges5 bronze badges

5

import sys
import subprocess

subprocess.call([sys.executable, 'abc.py', 'argument1', 'argument2'])

answered Apr 26, 2011 at 12:35

nosklo's user avatar

nosklonosklo

213k55 gold badges292 silver badges296 bronze badges

For more interesting scenarios, you could also look at the runpy module. Since python 2.7, it has the run_path function. E.g:

import runpy
import sys

# argv[0] will be replaced by runpy
# You could also skip this if you get sys.argv populated
# via other means
sys.argv = ['', 'arg1' 'arg2']
runpy.run_path('./abc.py', run_name='__main__')

answered Oct 21, 2015 at 12:48

petre's user avatar

petrepetre

1,41015 silver badges24 bronze badges

You’re confusing loading a module into the current interpreter process and calling a Python script externally.

The former can be done by importing the file you’re interested in. execfile is similar to importing but it simply evaluates the file rather than creates a module out of it. Similar to «sourcing» in a shell script.

The latter can be done using the subprocess module. You spawn off another instance of the interpreter and pass whatever parameters you want to that. This is similar to shelling out in a shell script using backticks.

answered Apr 26, 2011 at 10:31

Noufal Ibrahim's user avatar

Noufal IbrahimNoufal Ibrahim

70.5k12 gold badges134 silver badges169 bronze badges

0

You can’t pass command line arguments with execfile(). Look at subprocess instead.

answered Apr 26, 2011 at 10:21

Ignacio Vazquez-Abrams's user avatar

1

If you set PYTHONINSPECT in the python file you want to execute

[repl.py]

import os
import sys
from time import time 
os.environ['PYTHONINSPECT'] = 'True'
t=time()
argv=sys.argv[1:len(sys.argv)]

there is no need to use execfile, and you can directly run the file with arguments as usual in the shell:

python repl.py one two 3
>>> t
1513989378.880822
>>> argv
['one', 'two', '3']

answered Dec 23, 2017 at 0:37

loretoparisi's user avatar

loretoparisiloretoparisi

15.3k11 gold badges98 silver badges138 bronze badges

1

If you want to run the scripts in parallel and give them different arguments you can do like below.

import os
os.system("python script.py arg1 arg2 & python script.py arg11 arg22")

answered Feb 18, 2018 at 13:09

Mehmet nuri's user avatar

Mehmet nuriMehmet nuri

7806 silver badges7 bronze badges

3

Besides subprocess.call, you can also use subprocess.Popen. Like the following

subprocess.Popen(['./script', arg1, arg2])

answered Oct 21, 2015 at 13:49

Anakin Tung's user avatar

Anakin TungAnakin Tung

4195 silver badges17 bronze badges

This works:

subprocess.call("python abc.py arg1 arg2", shell=True)

answered May 26, 2020 at 15:34

amalik2205's user avatar

amalik2205amalik2205

3,8061 gold badge13 silver badges20 bronze badges

runfile('abc.py', ['arg1', 'arg2'])

answered Aug 23, 2020 at 8:43

D.P.'s user avatar

D.P.D.P.

214 bronze badges

This works for me :

import subprocess
subprocess.call(['python.exe', './abc.py', arg1, arg2])

answered Dec 13, 2021 at 19:55

Enrique Benito Casado's user avatar

При запуске скриптов, часто требуется указать какие-то дополнительные параметры, которые будут использованы в ходе работы программы. Конечно, можно при помощи функции input() получить данные от пользователя и сохранить их в переменных. Как говорится, дело вкуса. Но вместо множественного вызова функции input() есть намного более элегантное решение. Это передача параметров в скрипт python, непосредственно в командной строке — в момент вызова программы. Как это сделать? Давайте разберемся.

Для начала, наберите небольшую программу в своем редакторе. Сохраните её в папке C:PyScript под именем input_var.py. Разумеется, папку и файл можете назвать как угодно, но тогда не забудьте указать свои данные при вызове скрипта в командной строке.

1. #-*- coding: UTF-8 -*-
2. from sys import argv
3.
4. script, first, second, third = argv
5.
6. print ("Этот скрипт называется: ", script)
7. print ("Значение первой переменной: ", first)
8. print ("Значение второй переменной: ", second)
9. print ("Значение третьей переменной: ", third)

Как видите, программа очень маленькая. Но её вполне хватит для демонстрации способа передачи данных в скрипт. После того, как следуя приведенным выше инструкциям, вы набрали и сохранили программу, вызовите командную строку Windows. После этого укажите имя интерпретатора python, путь к вызываемому файлу и три значения, разделяя все пробелами, как на рисунке ниже:

Передача данных в скрипт Python

Рис. 1 Передача данных в скрипт Python

Если у вас скрипт хранится в другой папке — укажите свой путь к нему. После этого нажмите клавишу Enter на клавиатуре. В результате вы должны увидеть следующее:

Передача данных в скрипт Python

Рис. 2 Результат выполнения программы

А теперь давайте разберем, как же это все работает.

Во второй строке мы импортируем argv из модуля sys. Во многих языках переменных argv — стандартное имя. В этой переменной хранятся данных, которые вы передаете сценарию. Пока нам достаточно знать, что эта переменная работает как «контейнер», в котором мы можем передать данные скрипту.

В четвертой строке мы производим «распаковку» содержимого argv в переменные. Слово «распаковка» может показаться странным, но в данном случае оно наиболее подходит. Фактически, мы сообщаем интерпретатору Python, что он должен взять данные из argv и последовательно поместить их в переменные, которые мы указали с левой стороны. После этого мы можем работать с ними как с обычными переменными, которым присвоили значения.

Вы можете указать свои значения вместо «15 два 105», но число значений, которые вы передаете скрипту, должно строго соответствовать количеству переменных, в которые «распаковывается» содержимое argv. Иначе вы увидите сообщение об ошибке:

Передача данных в скрипт python

Рис. 3 Ошибка распаковки данных.

Это сообщение возникло потому что мы передали в скрипт Python недостаточно данных. Если конкретнее, то строка ValueError прямо сообщает, что необходимо 4 значения, но указано 3 (имя скрипта передается автоматически).

Не забывайте, что все данные, которые мы передаем в программу python являются строковыми значениями. Поэтому параметры «10» и «105» сначала необходимо преобразовать в числовой тип при помощи функции int(), а только потом использовать в математических операциях. Будьте внимательны!

Содержание

  • Обработка аргументов командной строки. Запуск программы с аргументами
    • Примеры без использования argparse
    • Использование библиотеки argparse
      • Простейший случай
      • Добавляем именованные параметры
    • Упражнение 1
  • Декораторы
    • Упражнение 2
    • Передача декоратором аргументов в функцию
    • Упражнение 3
    • Упражнение 4

Обработка аргументов командной строки. Запуск программы с аргументами

Параметры запуска, задаваемые через командную строку, чаще всего используют консольные программы, хотя программы с графическим интерфейсом тоже не брезгуют этой возможностью. Наверняка в жизни каждого программиста была ситуация, когда приходилось разбирать параметры командной строки, как правило, это не самая интересная часть программы, но без нее не обойтись. Эта статья посвящена тому, как Python облегчает жизнь программистам при решении этой задачи благодаря своей стандартной библиотеке argparse.

Примеры без использования argparse

Путь для начала у нас есть простейший скрипт на Python. Для определенности назовем скрипт coolprogram.py, это будет классический Hello World, над которым мы будем работать

if __name__ == "__main__":
   print ("Привет, мир!")

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

$ python coolprogram.py

или

$ python coolprogram.py Вася

Мы можем воспользоваться переменной argv из модуля sys. sys.argv содержит список параметров, переданных программе через командную строку, причем нулевой элемент списка — это имя нашего скрипта. Т.е. если у нас есть следующий скрипт с именем params.py:

import sys

if __name__ == "__main__":
    for param in sys.argv:
        print (param)

и мы запускаем его с помощью команды

python params.py

то в консоль будет выведена единственная строка:

params.py

Если же мы добавим несколько параметров,

python params.py param1 param2 param3

то эти параметры мы увидим в списке sys.argv, начиная с первого элемента:

params.py
param1
param2
param3

Здесь можно обратить внимание на то, что ссылка на интерпретатор Python в список этих параметров не входит, хотя он также присутствует в строке вызова нашего скрипта.

Вернемся к нашей задаче. Погрузившись в код на неделю, мы могли бы выдать заказчику следующий скрипт:

import sys

if __name__ == "__main__":
    if len (sys.argv) > 1:
        print ("Привет, {}!".format (sys.argv[1] ) )
    else:
        print ("Привет, мир!")

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

python coolprogram.py

то результат будет прежний

Привет, мир!

а если мы добавим параметр:

python coolprogram.py Вася

то программа поприветствует некоего Васю:

Привет, Вася!

Пока все легко и никаких проблем не возникает. Теперь предположим, что требования заказчика вновь изменились, и на этот раз он хочет, чтобы имя приветствуемого человека передавалось после именованного параметра —name или -n, причем нужно следить, что в командной строке передано только одно имя. С этого момента у нас начнется вермишель из конструкций if.

import sys

if __name__ == "__main__":
    if len (sys.argv) == 1:
        print ("Привет, мир!")
    else:
        if len (sys.argv) < 3:
            print ("Ошибка. Слишком мало параметров.")
            sys.exit (1)

        if len (sys.argv) > 3:
            print ("Ошибка. Слишком много параметров.")
            sys.exit (1)

        param_name = sys.argv[1]
        param_value = sys.argv[2]

        if (param_name == "--name" or
                param_name == "-n"):
            print ("Привет, {}!".format (param_value) )
        else:
            print ("Ошибка. Неизвестный параметр '{}'".format (param_name) )
            sys.exit (1)

Здесь мы проверяем ситуацию, что мы вообще не передали ни одного параметра, потом проверяем, что дополнительных параметров у нас ровно два, что они называются именно —name или -n, и, если нас все устраивает, выводим приветствие.

Как видите, код превратился в тихий ужас. Изменить логику работы в нем в дальнейшем будет очень сложно, а при увеличении количества параметров нужно будет срочно применять объектно-ориентированные меры по отделению логики работы программы от разбора командной строки. Разбор командной строки мы могли бы выделить в отдельный класс (или классы), но мы этого здесь делать не будем, поскольку все уже сделано в стандартной библиотеке Python, которая называется argparse.

Но перед тем, как перейти к библиотеке argparse, еще немного остановимся на sys.
Модуль sys обеспечивает доступ к некоторым переменным и функциям, взаимодействующим с интерпретатором python.
Самыми полезными являются:

  • sys.argv — список аргументов командной строки, передаваемых сценарию Python. sys.argv[0] является именем скрипта (пустой строкой в интерактивной оболочке).
  • sys.exit([arg]) — выход из Python. Функция exit принимает необязательный аргумент, обычно целое число, которое дает статус выхода. Ноль считается как успешное завершение. Обязательно проверьте, имеет ли ваша операционная система какие-либо особые значения для своих статусов выхода, чтобы вы могли следить за ними в своем собственном приложении. Обратите внимание на то, что когда вы вызываете exit, это вызовет исключение SystemExit, которое позволяет функциям очистки работать в конечных пунктах блоков try / except.
  • sys.stdin — стандартный поток ввода.
  • sys.stdout — стандартный поток вывода.
  • sys.stderr — стандартный поток ошибок.
    Stdin, stdout и stderr сопоставляются с файловыми объектами, которые соответствуют стандартным входам, выходам и потокам ошибок интерпретатора соответственно. Функция stdin используется для всех входов, используемых интерпретатором (за исключением скриптов), тогда как stdout используется для выходов операторов print. Эти потоки вывода можно переопределить, например для перенаправления логов вывода в графический интерфейс или в файл.
  • sys.__stdin__, sys.__stdout__, sys.__stderr__ — исходные значения потоков ввода, вывода и ошибок.

Использование библиотеки argparse

Простейший случай

Как как было сказано выше, стандартная библиотека argparse предназначена для облегчения разбора командной строки. На нее можно возложить проверку переданных параметров: их количество и обозначения, а уже после того, как эта проверка будет выполнена автоматически, использовать полученные параметры в логике своей программы.

Основа работы с командной строкой в библиотеке argparse является класс ArgumentParser. У его конструктора и методов довольно много параметров, все их рассматривать не будем, поэтому в дальнейшем рассмотрим работу этого класса на примерах, попутно обсуждая различные параметры.

Простейший принцип работы с argparse следующий:

  1. Создаем экземпляр класса ArgumentParser.
  2. Добавляем в него информацию об ожидаемых параметрах с помощью метода add_argument (по одному вызову на каждый параметр).
  3. Разбираем командную строку помощью метода parse_args, передавая ему полученные параметры командной строки (кроме нулевого элемента списка sys.argv).
  4. Начинаем использовать полученные параметры.

Для начала перепишем программу coolprogram.py с единственным параметром так, чтобы она использовала библиотеку argparse. Напомню, что данном случае мы ожидаем следующий синтаксис параметров:

python coolprogram.py [Имя]

Здесь [Имя] является необязательным параметром.

Наша программа с использованием argparse может выглядеть следующим образом:

import sys
import argparse

def createParser ():
    parser = argparse.ArgumentParser()
    parser.add_argument ('name', nargs='?')

    return parser


if __name__ == '__main__':
    parser = createParser()
    namespace = parser.parse_args()

    print (namespace)

    if namespace.name:
        print ("Привет, {}!".format (namespace.name) )
    else:
        print ("Привет, мир!")

На первый взгляд эта программа работает точно так же, как и раньше, хотя есть отличия, но мы их рассмотрим чуть позже. Пока разберемся с тем, что мы понаписали в программе.

Создание парсера вынесено в отдельную функцию, поскольку эта часть программы в будущем будет сильно изменяться и разрастаться. Сначала мы создали экземпляр класса ArgumentParser с параметрами по умолчанию. Что это за параметры, опять же, поговорим чуть позже.

Далее мы добавили ожидаемый параметр в командной строке с помощью метода add_argument. При этом такой параметр будет считаться позиционным, т.е. он должен стоять именно на этом месте и у него не будет никаких предварительных обозначений (мы их добавим позже в виде ‘-n’ или ‘—name’). Если бы мы не добавили именованный параметр nargs=’?’, то этот параметр был бы обязательным. nargs может принимать различные значения. Если бы мы ему присвоили целочисленное значение больше 0, то это бы означало, что мы ожидаем ровно такое же количество передаваемых параметров (точнее, считалось бы, что первый параметр ожидал бы список из N элементов, разделенных пробелами, этот случай мы рассмотрим позже). Также этот параметр может принимать значение ‘?’, ‘+’, ‘*’ и argparse.REMAINDER. Мы их не будем рассматривать, поскольку они важны в сочетании с необязательными именованными параметрами, которые могут располагаться как до, так и после нашего позиционного параметра. Тогда этот параметр будет показывать как интерпретировать список параметров, где будет заканчиваться один список параметров и начинаться другой.

Итак, мы создали парсер, после чего можно вызвать его метод parse_args для разбора командной строки. Если мы не укажем никакого параметра, это будет означать равносильно тому, что мы передадим в него все параметры из sys.argv кроме нулевого, который содержит имя нашей программы. т.е.

parser.parse_args (sys.argv[1:])

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

Если мы это сделаем и запустим программу с переданным параметром

python coolprogram.py Вася

, то увидим его в пространстве имен.

Namespace(name='Вася')

Если же теперь мы запустим программу без дополнительных параметров, то это значение будет равно None:

Namespace(name=None)

Мы можем изменить значение по умолчанию, что позволит нам несколько сократить программу. Пусть по умолчанию используется слово ‘мир’, ведь мы его приветствуем, если параметры не переданы. Для этого воспользуемся дополнительным именованным параметром default в методе add_argument.

import sys
import argparse


def createParser ():
    parser = argparse.ArgumentParser()
    parser.add_argument ('name', nargs='?', default='мир')

    return parser


if __name__ == '__main__':
    parser = createParser()
    namespace = parser.parse_args (sys.argv[1:])

    # print (namespace)

    print ("Привет, {}!".format (namespace.name) )

Программа продолжает работать точно также, как и раньше. Вы, наверное, заметили, что в предыдущем примере в метод parse_args ередаются параметры командной строки из sys.argv. Это сделано для того, чтобы показать, что список параметров мы можем передавать явно, при необходимости мы его можем предварительно обработать, хотя это вряд ли понадобится, ведь почти всю обработку можно возложить на плечи библиотеки argparse.

Добавляем именованные параметры

Теперь снова переделаем нашу программу таким образом, чтобы использовать именованные параметры. Напомню, что согласно последнему желанию (в смысле, для данной программы) заказчика имя приветствуемого человека должно передаваться после параметра —name или -n. С помощью pyparse сделать это проще простого — достаточно в качестве первых двух параметров метода add_argument передать эти имена параметров.

import sys
import argparse


def createParser ():
    parser = argparse.ArgumentParser()
    parser.add_argument ('-n', '--name', default='мир')

    return parser


if __name__ == '__main__':
    parser = createParser()
    namespace = parser.parse_args(sys.argv[1:])

    # print (namespace)

    print ("Привет, {}!".format (namespace.name) )

Теперь, если мы запустим программу без параметров, то увидим знакомое «Привет, мир!», а если мы запустим программу с помощью команды

python coolprogram.py -n Вася

или

python coolprogram.py --name Вася

То приветствовать программа будет Васю. Обратите внимание, что теперь в методе add_argument мы убрали параметр nargs=’?’ , поскольку все именованные параметры считаются необязательными. А если они не обязательные, то возникает вопрос, как поведет себя argparse, если этот параметр не передан? Для этого уберем параметр default в add_argument.

import sys
import argparse

def createParser ():
    parser = argparse.ArgumentParser()
    parser.add_argument ('-n', '--name')

    return parser


if __name__ == '__main__':
    parser = createParser()
    namespace = parser.parse_args(sys.argv[1:])

    print ("Привет, {}!".format (namespace.name) )

Если теперь запустить программу без параметров, то увидим приветствие великого None:

Привет, None!

Таким образом, если значение по умолчанию не указано, то оно считается равным None.

До этого мы задавали два имени для одного и того же параметра: длинное имя, начинающееся с «—» (—name) и короткое сокращение, начинающее ся с «-» (-n). При этом получение значение параметра из пространства имен осуществляется по длинному имени:

print ("Привет, {}!".format (namespace.name) )

Если мы не зададим длинное имя, то придется обращаться к параметру через его короткое имя (n):

import sys
import argparse

def createParser ():
    parser = argparse.ArgumentParser()
    parser.add_argument ('-n')

    return parser


if __name__ == '__main__':
    parser = createParser()
    namespace = parser.parse_args(sys.argv[1:])

    print (namespace)

    print ("Привет, {}!".format (namespace.n) )

При этом пространство имен будет выглядеть как:

Namespace(n='Вася')

Хорошо, с уменьшением количества имен параметров разобрались, но мы можем еще и увеличить количество имен, например, мы можем добавить для того же параметра еще новое имя —username, для этого достаточно его добавить следующим параметром метода add_argument:

import sys
import argparse

def createParser ():
    parser = argparse.ArgumentParser()
    parser.add_argument ('-n', '--name', '--username')

    return parser


if __name__ == '__main__':
    parser = createParser()
    namespace = parser.parse_args(sys.argv[1:])

    print (namespace)

    print ("Привет, {}!".format (namespace.name) )

Теперь мы можем использовать три варианта передачи параметров:

python coolprogram.py -n Вася
python coolprogram.py —name Вася
python coolprogram.py —username Вася

Все три варианта равнозначны, при этом надо обратить внимание, что при получении значения этого параметра используется первое длинное имя, т.е. name. Пространство имен при использовании всех трех вариантов вызова программы будет выглядеть одинаково:

Namespace(name='Вася')

Для полного погружения во все сложные случаи разбора параметров, можете ознакомиться со статьей https://jenyay.net/Programming/Argparse

Упражнение 1

Напишите консольную программу, которой на вход подается единственное число N (без имени или с именем -n), а программа печатает значение Nго числа Фибоначчи

Декораторы

Декораторы в Python и примеры их практического использования.

Итак, что же это такое? Для того, чтобы понять, как работают декораторы, в первую очередь следует вспомнить, что функции в python являются объектами, соответственно, их можно возвращать из другой функции или передавать в качестве аргумента. Также следует помнить, что функция в python может быть определена и внутри другой функции.

Вспомнив это, можно смело переходить к декораторам. Декораторы — это, по сути, «обёртки», которые дают нам возможность изменить поведение функции, не изменяя её код.

Создадим свой декоратор «вручную»:

def my_shiny_new_decorator(function_to_decorate):
    # Внутри себя декоратор определяет функцию-"обёртку". Она будет обёрнута вокруг декорируемой,
    # получая возможность исполнять произвольный код до и после неё.
    def the_wrapper_around_the_original_function():
        print("Я - код, который отработает до вызова функции")
        function_to_decorate() # Сама функция
        print("А я - код, срабатывающий после")
    # Вернём эту функцию
    return the_wrapper_around_the_original_function

# Представим теперь, что у нас есть функция, которую мы не планируем больше трогать.
def stand_alone_function():
    print("Я простая одинокая функция, ты ведь не посмеешь меня изменять?")

stand_alone_function()
# Однако, чтобы изменить её поведение, мы можем декорировать её, то есть просто передать декоратору,
# который обернет исходную функцию в любой код, который нам потребуется, и вернёт новую,
# готовую к использованию функцию:
stand_alone_function_decorated = my_shiny_new_decorator(stand_alone_function)
stand_alone_function_decorated()

Возможно мы бы хотели, чтобы каждый раз, во время вызова stand_alone_function, вместо неё вызывалась stand_alone_function_decorated. Для этого просто перезапишем stand_alone_function:

stand_alone_function = my_shiny_new_decorator(stand_alone_function)
stand_alone_function()

Собственно, это и есть декораторы. Вот так можно было записать предыдущий пример, используя синтаксис декораторов:

@my_shiny_new_decorator
def another_stand_alone_function():
    print("Оставь меня в покое")

another_stand_alone_function()

То есть, декораторы в python — это просто синтаксическая обертка для конструкций вида:

another_stand_alone_function = my_shiny_new_decorator(another_stand_alone_function)

Можно использовать несколько декораций для функций:

def bread(func):
    def wrapper():
        print()
        func()
        print("<______/>")
    return wrapper

def ingredients(func):
    def wrapper():
        print("#помидоры#")
        func()
        print("~салат~")
    return wrapper

def sandwich(food="--ветчина--"):
    print(food)

sandwich()
sandwich = bread(ingredients(sandwich))
sandwich()

И аналогично через декораторы:

@bread
@ingredients
def sandwich(food="--ветчина--"):
    print(food)

sandwich()

Не забываем, что так как порядок вызова функций имеет значение, то и порядок проставление декораторов так же имеет значение.

Упражнение 2

Напишите функцию, которая получает на вход список чисел и выдает ответ сколько в данном списке четных чисел. Напишите декоратор, который меняет поведение функции следующим образом: если четных чисел нет, то пишет «Нет(» а если их больше 10, то пишет «Очень много»

Передача декоратором аргументов в функцию

Однако, все декораторы, которые мы рассматривали, не имели одного очень важного функционала — передачи аргументов декорируемой функции. Собственно, это тоже несложно сделать.

Текстовый данные в языке пайтон описываются классом str:

def a_decorator_passing_arguments(function_to_decorate):
    def a_wrapper_accepting_arguments(arg1, arg2):
        print("Смотри, что я получил:", arg1, arg2)
        function_to_decorate(arg1, arg2)
    return a_wrapper_accepting_arguments

# Теперь, когда мы вызываем функцию, которую возвращает декоратор, мы вызываем её "обёртку",
# передаём ей аргументы и уже в свою очередь она передаёт их декорируемой функции
@a_decorator_passing_arguments
def print_full_name(first_name, last_name):
    print("Меня зовут", first_name, last_name)

print_full_name("Vasya", "Pupkin")

А теперь попробуем написать декоратор, принимающий аргументы:

def decorator_maker():
    print("Я создаю декораторы! Я буду вызван только раз: когда ты попросишь меня создать декоратор.")
    def my_decorator(func):
        print("Я - декоратор! Я буду вызван только раз: в момент декорирования функции.")
        def wrapped():
            print ("Я - обёртка вокруг декорируемой функции.n"
                   "Я буду вызвана каждый раз, когда ты вызываешь декорируемую функцию.n"
                   "Я возвращаю результат работы декорируемой функции.")
            return func()
        print("Я возвращаю обёрнутую функцию.")
        return wrapped
    print("Я возвращаю декоратор.")
    return my_decorator

# Давайте теперь создадим декоратор. Это всего лишь ещё один вызов функции
new_decorator = decorator_maker()
# Теперь декорируем функцию
def decorated_function():
    print("Я - декорируемая функция.")

decorated_function = new_decorator(decorated_function)
# Теперь наконец вызовем функцию:
decorated_function()

Теперь перепишем данный код с помощью декораторов:

@decorator_maker()
def decorated_function():
    print("Я - декорируемая функция.")

decorated_function()

Вернёмся к аргументам декораторов, ведь, если мы используем функцию, чтобы создавать декораторы «на лету», мы можем передавать ей любые аргументы, верно?

def decorator_maker_with_arguments(decorator_arg1, decorator_arg2):
    print("Я создаю декораторы! И я получил следующие аргументы:",
           decorator_arg1, decorator_arg2)
    def my_decorator(func):
        print("Я - декоратор. И ты всё же смог передать мне эти аргументы:",
               decorator_arg1, decorator_arg2)
        # Не перепутайте аргументы декораторов с аргументами функций!
        def wrapped(function_arg1, function_arg2):
            print ("Я - обёртка вокруг декорируемой функции.n"
                   "И я имею доступ ко всем аргументамn"
                   "t- и декоратора: {0} {1}n"
                   "t- и функции: {2} {3}n"
                   "Теперь я могу передать нужные аргументы дальше"
                   .format(decorator_arg1, decorator_arg2,
                           function_arg1, function_arg2))
            return func(function_arg1, function_arg2)
        return wrapped
    return my_decorator

@decorator_maker_with_arguments("Леонард", "Шелдон")
def decorated_function_with_arguments(function_arg1, function_arg2):
    print ("Я - декорируемая функция и я знаю только о своих аргументах: {0}"
           " {1}".format(function_arg1, function_arg2))

decorated_function_with_arguments("Раджеш", "Говард")

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

Некоторые особенности работы с декораторами
  1. Декораторы несколько замедляют вызов функции, не забывайте об этом.
  2. Вы не можете «раздекорировать» функцию. Безусловно, существуют трюки, позволяющие создать декоратор, который можно отсоединить от функции, но это плохая практика. Правильнее будет запомнить, что если функция декорирована — это не отменить.
  3. Декораторы оборачивают функции, что может затруднить отладку.

Упражнение 3

Напишите декоратор swap, который делает так, что задекорированная функция принимает все свои неименованные аргументы в порядке, обратном тому, в котором их передали (для аргументов с именем не вполне правильно учитывать порядок, в котором они были переданы).

Пример ожидаемого поведения:

@swap
def div(x, y, show=False):
    res = x / y
    if show:
        print(res)
    return res

div(2, 4, show=True)
>>> 2.0

Упражнение 4

Напишите декоратор, который принимает в качестве аргумента путь к файлу. Если данный декоратор добавить к функции, то в указанный файл будет логироваться информация вида:
  1. Время вызова функции
  2. Входящие аргументы
  3. Ответ return (если есть, если нет то логгировать ‘-‘)
  4. Время завершения работы функции
  5. Время работы функции

При создании консольных программ в Python очень часто необходимо разобрать параметры (аргументы) передаваемые через командную строку, это можно сделать используя переменную argv из модуля sys, а так же с помощью модуля argparse из стандартной библиотеки Pyhton.

Второй способ более предпочтительный и удобный, далее ему мы уделим больше внимания.

Статья ниже не является полным описание всех возможностей модуля argparse, это просто общий обзор.

Ниже я иногда пишу аргументы командной строки, иногда параметры командной строки… Имеется ввиду одно и тоже smiley

Получение параметров без использования argparse

Например, мы хотим написать программу после запуска выводящую в консоль «Привет <переданное_имя>». Имя мы будем передавать через параметр в командной строке, далее его нужно получить в нашей программе. Как это сделать?

Мы можем сделать это используя стандартный модуль sys и его переменную argv, она содержит список переданных параметров (нулевой элемент списка содержит имя нашего скрипта).

Другими словами, чтобы вывести имя, которое мы передаем аргументом, необходимо обратиться к  sys.argv[1]:

import sys
print(f'Привет {sys.argv[1]}')

Сохраним код в файле hello.py и запустим его с параметром «Александр» (аргументом):

python hello.py Александр

Получаем ожидаемое:

Привет Александр

Но если попытаться запустить скрипт без параметра, то получаем ошибку поскольку в списке нет элемента с индексом 1. Исправим это сделав проверку на наличии передаваемого параметра и если он не передается, будет выводиться «Привет мир!»

import sys

if len(sys.argv) == 1:
    print('Привет мир!')
else:
    print(f'Привет {sys.argv[1]}')

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

import sys

if len(sys.argv) == 1:
    print('Привет мир!')
else:
    p_name = sys.argv[1]
    p_value = sys.argv[2]

    if p_name == '--name':
        print(f'Привет {p_value}')
    else:
        print(f'Неизвесный параметр {p_name}')

Запустив скрипт таким образом:

python hello.py --name Александр

Получаем нужный результат, если в место «—name» передать другое значение, то получаем предупреждение.

Но, если мы передадим один параметр вместо двух, то скрипт не запуститься, нам необходимо добавить еще один if для проверки существование минимум двух параметров.

А если нам нужно добавить еще несколько параметров, а если не все из них обязательные… короче код начнется превращаться в ужас, вот здесь нам на помощь и придет модуль argparse стандартной питоновской библиотеки.

Использование модуля argparse

Этот модуль облегчит нам разбор и дальнейшее использование передаваемых скрипту аргументов из командной строки.

Начнем переписывать наш пример:

import argparse

parser = argparse.ArgumentParser()

parser.add_argument('name', nargs='?', default='мир!')

args = parser.parse_args()

print(f'Привет {args.name}')

Сохраним код в новый файл hello2.py и выполним передав ему в качестве параметра «Александр»:

python hello2.py Александр

Мы получим то, что требовалось:

Привет Александр

Разберем подробнее строку:

parser.add_argument('name', nargs='?', default='мир!')

В ней мы с помощью метода add_argument и передаваемых ему параметров, задали необязательный (для этого указали nargs=’?’) позиционный аргумент. Если аргумент не передается, то он принимает значение указанное в default.

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

Продолжим доработку кода. Теперь мы хотим, чтобы Имя передавалось именованным параметром —name

Для этого всего лишь надо изменить одну строку создания аргумента

parser.add_argument('--name', default='мир!')

Теперь можно запустить скрипт с именованным параметром —name:

python hello2.py --name Александр

Мы получим «Привет Александр», а при отсутствии параметра, будет выводится значение по умолчанию «Привет мир».

У названия параметра может быть краткая форма, она записывается с одним ««, например:

parser.add_argument('-n', '--name', default='мир!')

А что если в качестве параметра —name мы заходим передать Имя + Фамилия?

python hello2.py --name Александр Третьяков

Выполнив это сейчас мы получим ошибку error: unrecognized arguments: Третьяков поскольку модуль argparse решил что фамилия это отдельный аргумент.

Чтобы поправить ситуацию, используем дополнительный параметр метода add_argument — nargs со значением «+», который обозначает, что мы ожидаем одно или более значений аргумента.

Теперь повторно вызвав скрипт, получим все переданные параметры в виде списка:

Привет ['Александр', 'Третьяков']

Выбор агрументов из определенных вариантов

Иногда может потребоваться, чтобы пользователь программы указал аргумент из заранее заданных вариантов (например нужно указать расширение конвертируемого файла или качество сохраняемого видео).

Если брать наш пример выше, можем добавить, чтобы скрипт принимал только определенные имена: Александр, Екатерина, Татьяна, Евгений. Для этого добавим в метод add_argument параметр choices, в котором укажем список возможных значений параметра (в нашем случае список имен).

parser.add_argument ('-n', '--name', choices=['Александр', 'Екатерина', 'Татьяна', 'Евгений'])

Теперь при вызове скрипта мы должны обязательно указать параметр —name со значением из этого списка иначе возникнет ошибка:

python hello2.py --name Екатерина

Получим:

Привет Екатерина

А если попробуем передать имя не из одобренного списка:

hello2.py --name Ольга

Получим ошибку:

usage: hello2.py [-h] [-n {Александр,Екатерина,Татьяна,Евгений}]

hello2.py: error: argument -n/--name: invalid choice: 'Ольга' (choose from 'Александр', 'Екатерина', 'Татьяна', 'Евгений')

Справка (помощь) по аргументам

Выше мы ограничили список возможных значений аргумента —name четырьмя именами, но как узнать об этом пользователю, который в первый раз использует скрипт, ему придаться вчитываться в текст ошибки, чтобы понять чего от него хочет программа. Как пользователю узнать о всех возможных аргументах, порядке их применения и их назначении?

Для этого мы можем оформить справку для программы, которая будет вызываться аргументом —help или -h. В справочной информации мы сможем указать название и версию программы, копирайт, описание того, что она делает, и список ожидаемых параметров.

Итак изменим 2 строчки нашего кода, добавив в него справочную информацию:

parser = argparse.ArgumentParser(
    prog='Greeting Script',
    description='Программа, которая говорит "Привет"',
    epilog='(c) Информация об авторе программы'

)

parser.add_argument ('-n', '--name', choices=['Александр', 'Екатерина', 'Татьяна', 'Евгений'], help='Список из имен, которые я могу приветствовать')

Теперь вызвав:

python hello2.py --help

Мы получим справку о нашей программе:

usage: Greeting Script [-h] [-n {Александр,Екатерина,Татьяна,Евгений}]

Программа, которая говорит "Привет"

optional arguments:
  -h, --help            show this help message and exit
  -n {Александр,Екатерина,Татьяна,Евгений}, --name {Александр,Екатерина,Татьяна,Евгений}
                        Список из имен, которые я могу приветствовать

(c) Информация об авторе программы

Аргументы как флаги

А что если мы хотим сделать так, чтобы при указании флага -bye программа говорила нам «До свидания»?

Для этого добавим строку:

parser.add_argument ('-bye', action='store_const', const=True, help='Установите, если нужно ли прощаться с пользователем')

В метод add_argument мы добавили 2 новых параметра. Первый — action, он предназначен для выполнения некоторых действий над значениями переданного аргумента. В нашем случае мы передали значение параметра action — store_const,  оно обозначает, что если данный аргумент (‘-bye’) указан, то он всегда будет принимать значение, указанное в другом параметре метода add_argument — const. А если аргумент передан не будет, то его значение будет равно None.

Так же в конце скрипта добавим вывод «До свидания», в случае установленного флага -bye:

if args.bye:
    print ('До свидания')

Теперь если добавить флаг -bye при вызове скрипта:

python hello2.py --name Александр -bye

Получим:

Привет Александр
До свидания

Без добавления -bye мы получим просто:

Привет Александр

Флаги со значениями True и False используются часто, поэтому для этих целей предусмотрено 2 специальных значения для параметра action: store_true и store_false.

Можно переписать наш код так:

parser.add_argument ('-bye', action='store_true', help='Установите, если нужно ли прощаться с пользователем')

Мы использовали store_true, т.е. если параметр ‘-bye’ передан, он примет значение True.

Кстати, выше мы увидели что для добавление второго, третьего и т.д. аргумента, нам нужно просто еще раз вызвать метод add_argument и передать ему значения параметра.

Окончательный код нашего файла hello2.py:

import argparse

parser = argparse.ArgumentParser(
    prog='Greeting Script',
    description='Программа, которая говорит "Привет"',
    epilog='(c) Информация об авторе программы'

)

parser.add_argument ('-n', '--name', choices=['Александр', 'Екатерина', 'Татьяна', 'Евгений'], help='Список из имен, которые я могу приветствовать')
parser.add_argument ('-bye', action='store_true', help='Установите, если нужно ли прощаться с пользователем')

args = parser.parse_args()

print(f'Привет {args.name}')

if args.bye:
    print ('До свидания')

На этом все, думаю общее представление о модуле argsparse вы получили, подробнее о нем можно почитать в  официальной документации https://docs.python.org/3/library/argparse.html.

Понравилась статья? Поделить с друзьями:
  • Windows занимает слишком много места на диске
  • Windows загружается только через boot menu
  • Windows зависает через несколько минут после загрузки
  • Windows зависает после установки драйверов видеокарты
  • Windows завершить сеанс через командную строку