Написать скрипт для windows на python

Здарова, щеглы, сегодня мы своими руками будем писать скрипт на Python. Нам понадобятся: интерпретатор Python 3 под "какая-там-у-вас-ОС", текстовый редактор с подсветкой синтаксиса, например…

Здарова, щеглы, сегодня мы своими руками будем писать скрипт на Python. Нам понадобятся: интерпретатор Python 3 под «какая-там-у-вас-ОС», текстовый редактор с подсветкой синтаксиса, например, Sublime Text, Google, упаковка прамирацетама, бутылка минеральной воды и 60 минут свободного времени.
Перед тем как писать скрипт, мы должны определиться, что он вообще будет делать. Делать он будет следующее: получив на вход домен и диапазон IP-адресов, многопоточно проходить список этих адресов, совершать HTTP-запрос к каждому, в попытках понять, на каком же из них размещен искомый домен. Зачем это нужно? Бывают ситуации, когда IP-адрес домена закрыт Cloudflare, или Stormwall, или Incapsula, или еще чем-нибудь, WHOIS история не выдает ничего интересного, в DNS-записях такая же канитель, а, внезапно, один из поддоменов ресолвится в адрес из некоторой подсети, которая не принадлежит сервису защиты. И в этот момент нам становится интересно, вдруг и основной домен размещен в той же самой подсети.

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

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

58

59

60

61

62

63

64

65

66

67

68

69

70

71

72

73

74

75

76

77

78

79

80

81

82

83

84

85

86

87

88

89

90

91

92

93

94

95

96

97

98

99

100

import argparse

import logging

import coloredlogs

import ssl

import concurrent.futures

import urllib.request

from netaddr import IPNetwork

from collections import deque

VERSION = 0.1

def setup_args():

parser = argparse.ArgumentParser(

description = ‘Domain Seeker v’ + str(VERSION) + ‘ (c) Kaimi (kaimi.io)’,

epilog = »,

formatter_class = argparse.ArgumentDefaultsHelpFormatter

)

parser.add_argument(

‘-d’,

‘—domains’,

help = ‘Domain list to discover’,

type = str,

required = True

)

parser.add_argument(

‘-i’,

‘—ips’,

help = ‘IP list (ranges) to scan for domains’,

type = str,

required = True

)

parser.add_argument(

‘—https’,

help = ‘Check HTTPS in addition to HTTP’,

action = ‘store_true’

)

parser.add_argument(

‘—codes’,

help = ‘HTTP-codes list that will be considered as good’,

type = str,

default = ‘200,301,302,401,403’

)

parser.add_argument(

‘—separator’,

help = ‘IP/Domain/HTTP-codes list separator’,

type = str,

default = ‘,’

)

parser.add_argument(

‘—include’,

help = ‘Show results containing provided string’,

type = str

)

parser.add_argument(

‘—exclude’,

help = ‘Hide results containing provided string’,

type = str

)

parser.add_argument(

‘—agent’,

help = ‘User-Agent value for HTTP-requests’,

type = str,

default = ‘Mozilla/5.0 (Windows NT 6.1; WOW64; rv:40.0) Gecko/20100101 Firefox/40.1’

)

parser.add_argument(

‘—http-port’,

help = ‘HTTP port’,

type = int,

default = 80

)

parser.add_argument(

‘—https-port’,

help = ‘HTTPS port’,

type = int,

default = 443

)

parser.add_argument(

‘—timeout’,

help = ‘HTTP-request timeout’,

type = int,

default = 5

)

parser.add_argument(

‘—threads’,

help = ‘Number of threads’,

type = int,

default = 2

)

args = parser.parse_args()

return args

if __name__ == ‘__main__’:

main()

Ни одного комментария, какие-то import, непонятные аргументы командной строки и еще эти две последние строчки… Но будьте спокойны, все нормально, это я вам как мастер программирования на Python с 30-минутным стажем говорю. Тем более, как известно, Google не врет, а официальная документация по Python — это вообще неоспоримая истина.
Так что же мы все-таки сделали в вышеописанном фрагменте кода? Мы подключили модули для работы с аргументами коммандной строки, модули для логирования (потокобезопасные между прочим!), модуль для работы с SSL (для одной мелочи, связанной с HTTPS-запросами), модуль для создания пула потоков, и, наконец, модули для совершения HTTP-запросов, работы с IP-адресами и двухсторонней очередью (по поводу различных типов импорта можно почитать здесь).
После этого мы, в соответствии с документацией по модулю argparse, создали вспомогательную функцию, которая будет обрабатывать аргументы, переданные скрипту при запуске из командной строки. Как видите, в скрипте будет предусмотрена работа со списком доменов/IP-диапазонов, а также возможность фильтрации результатов по ключевым словам и по кодам состояния HTTP и еще пара мелочей, как, например, смена User-Agent и опциональная проверка HTTPS-версии искомого ресурса. Последние две строки в основном используются для разделения кода, который будет выполнен при запуске самого скрипта и при импортировании в другой скрипт. В общем тут все сложно, все так пишут. Мы тоже так будем писать. Можно было бы немного модифицировать этот код, например, добавив возврат разных статусов системе в зависимости от того, как отработала функция main, добавить argv в качестве аргумента, и так далее, но мы изучаем Python только 10 минут и ленимся вчитываться в документацию.

Делаем перерыв и выпиваем глоток освежающей минеральной воды.

Поехали дальше.

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

def main():

# Обрабатываем аргументы и инициализируем логирование

# с блекджеком и цветными записями

args = setup_args()

coloredlogs.install()

# Сообщаем бесполезную информацию, а также запускаем цикл проверки

logging.info(«Starting…»)

try:

check_loop(args)

except Exception as exception:

logging.error(exception)

logging.info(«Finished»)

def check_loop(args):

# Создаем пул потоков, еще немного обрабатываем переданные аргументы

# и формируем очередь заданий

with concurrent.futures.ThreadPoolExecutor(max_workers = args.threads) as pool:

domains = args.domains.split(args.separator)

ips = args.ips.split(args.separator)

codes = args.codes.split(args.separator)

tasks = deque([])

for entry in ips:

ip_list = IPNetwork(entry)

for ip in ip_list:

for domain in domains:

tasks.append(

pool.submit(

check_ip, domain, ip, args, codes

)

)

# Обрабатываем результаты и выводим найденные пары домен-IP

for task in concurrent.futures.as_completed(tasks):

try:

result = task.result()

except Exception as exception:

logging.error(exception)

else:

if result != None:

data = str(result[0])

if(

( args.exclude == None and args.include == None )

or

( args.exclude and args.exclude not in data )

or

( args.include and args.include in data )

):

logging.critical(«[+] « + args.separator.join(result[1:]))

В коде появился минимум комментариев. Это прогресс. Надо войти в кураж (не зря мы заготовили прамирацетам) и дописать одну единственную функцию, которая будет осуществлять, непосредственно, проверку. Ее имя уже упомянуто в коде выше: check_ip.

30 минут спустя

Хорошо-то как. Не зря я говорил, что понадобится час времени. Продолжим.

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

def check_ip(domain, ip, args, codes):

# Преобразуем IP из числа в строку

# Магическая code-flow переменная для совершения двух проверок

# И бесполезное логирование

ip = str(ip)

check_https = False

logging.info(«Checking « + args.separator.join([ip, domain]))

while True:

# Задаем порт и схему для запроса в зависимости от магической переменной

schema = ‘https://’ if check_https else ‘http://’;

port = str(args.https_port) if check_https else str(args.http_port)

request = urllib.request.Request(

schema + ip + ‘:’ + port + ‘/’,

data = None,

headers = {

‘User-Agent’: args.agent,

‘Host’: domain

}

)

# Совершаем запрос, и если получаем удовлетворительный код состояни HTTP,

# то возвращаем содержимое ответа сервера, а также домен и IP

try:

response = urllib.request.urlopen(

request,

data = None,

timeout = args.timeout,

context = ssl._create_unverified_context()

)

data = response.read()

return [data, ip, domain]

except urllib.error.HTTPError as exception:

if str(exception.code) in codes:

data = exception.fp.read()

return [data, ip, domain]

except Exception:

pass

if args.https and not check_https:

check_https = True

continue

return None

В общем-то весь наш скрипт готов. Приступаем к тестированию.

terminal

Неожиданно узнаем, что у блога есть альтернативный IP-адрес. И действительно:

curl i ‘http://188.226.181.47/’ header ‘Host: kaimi.io’

HTTP/1.1 301 Moved Permanently

Server: nginx/1.4.6 (Ubuntu)

Date: Sun, 02 Oct 2016 13:52:43 GMT

ContentType: text/html

ContentLength: 193

Connection: keepalive

Location: https://kaimi.io/

<html>

<head><title>301 Moved Permanently</title></head>

<body bgcolor=«white»>

<center><h1>301 Moved Permanently</h1></center>

<hr><center>nginx/1.4.6 (Ubuntu)</center>

</body>

</html>

Однако:

curl i ‘https://188.226.181.47/’ header ‘Host: kaimi.io’

curl: (51) SSL: certificate subject name (*.polygraph.io) does not match target host name ‘188.226.181.47’

Какой-то левый хост обрабатывает запросы. Почему? Потому что это прокси, который реагирует на содержимое заголовка Host. В общем скрипт готов, по крайней мере альфа-версия скрипта. Если вам понравилось — подписывайтесь, ставьте лайки, шлите pull-реквесты на github.

В этой небольшой статье речь пойдет о том, можно ли легко использовать Python для написания скриптов вместо Bash/Sh. Первый вопрос, который возникнет у читателя, пожалуй, а почему, собственно, не использовать Bash/Sh, которые специально были для этого созданы? Созданы они были достаточно давно и, на мой взгляд, имеют достаточно специфичный синтаксис, не сильно похожий на остальные языки, который достаточно сложно запомнить, если вы не администратор 50+ левела. Помните, ли вы навскидку как написать на нем простой if?

if [ $# -ne "$ARGCOUNT" ]
then
    echo "Usage: `basename $0` filename"
    exit $E_WRONGARGS
fi

Элементарно правда? Интуитивно понятный синтаксис. :)

Тем не менее в python эти конструкции намного проще. Каждый раз когда я пишу что то на баше, то непременно лезу в поисковик чтобы вспомнить как писать простой if, switch или что-то еще. Присвоение я уже запомнил. :) В Python все иначе. Я хоть и не пишу на нем круглые сутки, но никогда не приходилось лезть и смотреть как там сделать простой цикл, потому что синтаксис языка простой и интуитивный. Плюс ко всему он намного ближе к остальным мейнстримовым языкам типа java или c++, чем Bash/Sh.

Также в стандартной и прочих библиотеках Python есть намного более удобные библиотеки чем консольные утилиты. Скажем, вы хотите распарсить json, xml, yaml. Знаете какой я недавно видел код в баше чтобы сделать это? Правильно:

python -c "import json; json.loads..." :)

И это был не мой код. Это был код баше/питоно нейтрального человека.

То же самое с регексом, sed бесспорно удобная утилита, но как много людей помнит как правильно ее использовать? Ну кроме Lee E. McMahon, который ее создал. Да впринципе многие помнят, даже я помню как делать простые вещи. Но, на мой взгляд, в Python модуль re намного удобнее.

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

Велкам под кат.

Введение

Shell python ничем не отличается от простого Python кроме одной детали. Выражения внутри grave accent символов ( ` ) в отличие от Python не является eval, а обозначает выполнение команды в шелле. Например

`ls -l`

выполнит ls -l как shell команду. Также возможно написать все это без ` в конце строки

`ls -l

и это тоже будет корректным синтаксисом.

Можно выполнять сразу несколько команд на разных строках

`
echo test > test.txt
cat test.txt
`

и команды, занимающие несколько строк

`echo This is 
  a very long 
  line

Выполнение каждого выражения в shellpy возвращается объект класса Result

result = `ls -l

Это можно быть либо Result либо InteractiveResult (Ссылки на гитхаб с документацией, можно и потом посмотреть :) ). Давайте начнем с простого результата. Из него можно легко получить код возврата выполненной команды

result = `ls -l
print result.returncode

И текст из stdout и stderr

result = `ls -l
result_text = result.stdout
result_error = result.stderr

Можно также пробежаться по всем строкам stdout выполненной команды в цикле

result = `ls -l
for line in result:
    print line.upper()

и так далее.

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

result = `ls -l
if result:
    print 'Return code for ls -l was 0'

Или же более простым способом получить текст из stdout

result = `ls -l
print result

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

Это ж не валидный синтаксис Python получается, как все работает то?

Магия конечно, как еще :) Да, друзья мои, мне пришлось использовать препроцессинг, каюсь, но другого способа я не нашел. Я видел другие библиотеки, которые делают нечто подобное, не нарушая синтаксиса языка вроде

from sh import ifconfig
print(ifconfig("wlan0"))

Но меня такой синтаксис не устраивал, поскольку даже несмотря на сложности, хотелось получить best user experience ©, а для меня это значит насколько это возможно простое и близкое к его величеству Шеллу написание команд.

Знакомый с темой читатель спросит, чем IPython то тебя не устроил, там ж почти как у тебя только значок другой ставить надо, может ты просто велосипедист, которому лень заглянуть в поисковик? И правда он выглядит вот так:

lines = !ls -l

Я его пытался использовать но встретил пару серьезных проблем, с которыми ужиться не смог. Самая главная из них, то что нет простого импорта как в Python. То есть ты не можешь написать какой-то код на самом ipython и легко его переиспользовать в других местах. Невозможно написать для своего ipython модуля

import myipythomodule

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

В shellpy код переиспользуется легко и импортируется точно так же как и в обычном python. Предположим у нас есть модуль common в котором мы храним очень полезный код. Заглянем в директорию с этим модулем

ls common/
common.spy  __init__.spy

Итак, что у нас тут есть, ну во первых init, но с расширением .spy. Это и является отличительной чертой spy модуля от обычного. Посмотрим также внутрь файла common.spy, что там интересного

def common_func():
    return `echo 5

Мы видим что тут объявлена функция, которая внутри себя использует shellpy синтаксис чтобы вернуть результат выполнения `echo 5. Как этот модуль используется в коде? А вот как

from common.common import common_func

print('Result of imported function is ' + str(common_func()))

Видите? Как в обычном Python, просто взяли и заимпортировали.

Как же все работает. Это работает с помощью PEP 0302 — New Import Hooks. Когда вы импортируете что-то в своем коде то вначале Python спрашивает у хука, нет ли тут чего-то твоего, хук просматривает PYTHONPATH на наличие файлов *.spy или модулей shellpython. Если ничего нет, то так и говорит: «Ничего нету, импортируй сам». Если же он находит что-то там, то хук занимается импортом самостоятельно. А именно, он делает препроцессинг файла в обычный python и складывает все это добро в temp директорию операционной системы. Записав новый Python файл или модуль он добавляет его в PYTHONPATH и за дело берется уже самый обыкновенный импорт.

Давайте же скорее посмотрим на какой-нибудь пример

Этот скрипт скачивает аватар юзера Python с Github и кладет его в temp директорию

    import json
    import os
    import tempfile

    # с помощью curl получает ответ от апи гитхаба
    answer = `curl https://api.github.com/users/python

    # синтаксический сахар чтобы сравнить результат выполнение с нулем
    if answer:
        answer_json = json.loads(answer.stdout)
        avatar_url = answer_json['avatar_url']

        destination = os.path.join(tempfile.gettempdir(), 'python.png')

        # в этот раз скачиваем саму картинку
        result = `curl {avatar_url} > {destination}
        if result:
            # если проблем не возникло, то показываем картинку 
            p`ls -l {destination}
        else:
            print('Failed to download avatar')

        print('Avatar downloaded')
    else:
        print('Failed to access github api')

Красота…

Установка

Shellpython можно установить двумя способами: pip install shellpy или склонировав репозиторий и выполнив setup.py install. После этого у вас появится утилита shellpy.

Запустим же что-нибудь

После установки можно потестировать shellpython на примерах, которые доступны прямо в репозитории.

shellpy example/curl.spy

shellpy example/git.spy

Также здесь есть allinone примеры, которые называются так, потому что тестируют все-все функции, которые есть в shellpy. Загляните туда, чтобы лучше узнать что же там еще такого есть, либо просто выполните

shellpy example/allinone/test.spy

Для третьего Python команда выглядит вот так

shellpy example/allinone/test3.spy

Совместимость

Это работает на Linux и должно работать на Mac для Python 2.x и 3.x. На виндовсе пока не работает, но проблем никаких для работы нет, так как все писалось с использованием кроссплатформенных библиотек и ничего платформоспецифичного в коде нет. Просто не дошли руки еще, чтобы потестировать на виндовсе. Мака у меня тоже нет, но вроде у друга работало :) Если у вас есть мак и у вас все нормально, скажите пожалуйста.

Если найдете проблемы — пишите в коммент, либо сюда Join the chat at https://gitter.im/lamerman/shellpy либо телеграфируйте как-нибудь :)

Документация (на английском)

Wiki

Можно ли законтрибьютить

Конечно :)

Оно мне ничего в продакшене не разломает?

Сейчас версия 0.4.0, это не стейбл и продакшн процессы пока лучше не завязывать на скрипт, подождав пока все отладится. Но в девелопменте, CI можно использовать вполне. Все это покрыто тестами и работает :) Build Status

P.s.

Пишите ваши отзывы об идее в целом и о реализации в частности, а также о проблемах, пожеланиях, всех рад услышать :) Заводите Issues еще в гитхабе, там их уже много :)

Желание изучить питон было давно. Я много где слышал что он хорошо подходит для прототипов, скриптов и небольших приложений. Он отличается высокой скоростью разработки и низким порогом вхождения. Динамичность — непривычно, но решаемо.

И вот, написал первый скрипт. Он оптимизирует перемещение на «сегодня» просроченных задач в тудуисте. Перенос в приложении выполняется в 3 действия: выделить задачи с зажатым шифтом, пройти через пункты меню и нажать заветную кнопку: «перенести на сегодня». Это не всегда получается с одной попытки. Время для автоматизации!

Установка Python 3

Не нашел причин, чтобы начать знакомство не с 3 версией питона. И, так как в Mac OS X El Capitan, установлена версия 2.7, то рассмотрим простой способ установки Python 3.

Понадобится менеджер пакетов Homebrew. У кого нет — советую. Для его установки введем в терминале:

ruby -e "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install)"

Теперь установим третий питон:

Проверить работоспособность можно набрав в консоли python3.

Получение пакета для работы с тудуистом

Следующий этап — установка библиотеки для работы с АПИ тудуиста. Воспользуемся менеджером пакетов pip3, который поставляется вместе с Python 3:

pip3 install todoist-python

Напоминаю о командной оболочке Zsh, о которой я писал ранее. Подключив плагины brew и pip можно добавить автодополнение для команд и пакетов.

Среда разработки

Автодополнение, рефакторинг, отладка — все это помогает на любых стадиях изучения языка. Поэтому я воспользовался IDE от JetBrains — PyCharm CE. Это бесплатная версия, в которой есть все необходимое.

Стиль кода и именования

Планирутся отдельная статья. А пока — о стиле именования.

Имена функций, методов и переменных экземпляров классов должны состоять из маленьких букв, а слова разделяться символами подчеркивания:

Стиль mixedCase допускается в тех местах, где уже преобладает такой стиль, для сохранения обратной совместимости:

Для атрибутов и непубличных методов используется один символ подчёркивания перед именем:

Итерация и получение значений из коллекций

Библиотека todoist возвращает на запрос о просроченных задачах словарь или список. Возник вопрос: как работать с коллекциями?

Итерация оказалась похожа на foreach из C#:

for overdue_item in overdue_items:
    item = api.items.get_by_id(overdue_item['id'])
    print item

Для получения значения словаря есть 2 способа . Первый — обращение по ключу:

Но, если значения нет, возникнет ошибка — KeyError: 'id'. Поэтому при неуверенности, используйте get:

id = overdue_item.get('id')

Если значение отсутствует, метод вернет значение по умолчанию — None.

Преобразование и работа с датой

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

Разберем построчно код из моего скрипта:

item_due_date = datetime.strptime(item['due_date_utc'], '%a %d %b %Y %H:%M:%S %z')
delta = datetime.now(timezone.utc).date() - item_due_date.date()
item_today_date = item_due_date + timedelta(days=delta.days)
item.update(due_date_utc=item_today_date.strftime('%Y-%m-%dT%H:%M:%S'))
  1. По ключу due_date_utc получаем дату в формате "Fri 26 Sep 2014 08:25:05 +0000". Выражением %a %d %b %Y %H:%M:%S %z переводим в понятный питону формат. Документация по значениям переменных из выражения.
  2. Находим разницу между текущей датой и датой полученного объекта.
  3. Актуализируем дату объекта, добавляя к нему полученную разницу дней.
  4. Переведем дату в строку используя %Y-%m-%dT%H:%M:%S и отправим изменения в тудуист.

Типы выполнения модуля с кодом

Часто, читая код на гитхабе, встречал конструкцию:

if __name__ == "__main__":
    ...

Выясним ее предназначение.

Когда исполняется файл с кодом, выполняются все команды на нулевом уровне: задаются специальные переменные, импортируются модули, определяются функции и классы. Одна из специальных переменных — __name__. Она хранит имя модуля, который вызвал скрипт.

Например, модуль вызвали из файла foo.py:

Переменная __name__ примет значение foo. Если вызвать скрипт напрямую из терминала:

__name__ инициализируется значением __main__. И тогда выполнится весть код из условия if __name__ == "__main__":. Получается, модуль может работать и библиотекой и независимым приложением.

Добавление атрибутов командной строки

Мой скрипт может принимать значение токена АПИ тудуиста. Для этого скрипт вызывается с параметром -t:

python TodoistOverdue.py -t 0123456789abcdef0123456789abcdef01234567

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

parser = argparse.ArgumentParser(description="Moving overdue tasks for today in todoist")
parser.add_argument("-t", "--token", help="Todoist API token")
args = parser.parse_args()
  1. Инициализируем класс ArgumentParser, помогающий работать с командной строкой, и зададим описание скрипта.
  2. Добавим аргумент, задаваемый ключом ’-t’ или ’--token’. В параметре help указываем описание, показываемое при вызове скрипта с ключом -h.
  3. Переводим строки аргументов в объекты и присваиваем их как атрибуты к переменной.

Теперь, при запуске скрипта с ключом -t, в переменной args.token будет храниться значение введенного токена. Про остальные параметры и методы можно узнать в документации python.

Чтение и запись в файл конфигурации

Полученный токен хранится в конфигурационном файле. Рассмотрим код для доступа, чтения и записи значения:

Чтение и запись в файл конфигурации

Полученный токен хранится в конфигурационном файле. Рассмотрим код для доступа, чтения и записи значения:

config = configparser.ConfigParser()
config.read(expanduser('~') + "/.todoist")
token = args.token
if token is None:
    token = config['Global']['TokenAPI']
else:
    config['Global'] = {'TokenAPI': token}
    with open(expanduser('~') + "/.todoist", 'w') as configfile:
        config.write(configfile)
  1. Инициализируем ConfigParser и читаем файл из домашней директории пользователя. expanduser('~') позволяет получить путь к домашней директории в любой операционной системе.
  2. Читаем конфиг как словарь: config['Global']['TokenAPI']. Сначала обращаемся к секции со значением, следом — к ключу.
  3. В блоке else записываем значение токена, если оно было указано при запуске. После конфигурационный файл записывается на диск.

Мне понравилось, как просто записать изменения в файл. В C# для этого надо открывать потоки, указывать дополнительную информацию, здесь это просто 2 строчки. Возьми это и запиши сюда, все.

Документация для ConfigParser. Информацию о вводе и выводе в Python 3.

Заключение

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

Полный скрипт TodoistOverdue.py из статьи лежит в gist.

Полезные ссылки

— Как запускать скрипты в Mac Os X без указания полного пути. Stackoverflow.
— Изучить питон за несколько минут (learnxinyminutes.com). Русская и английская версия.
— Документация для Python 3.5.х.

В этом руководстве рассказывается о том, как создать и как запустить скрипт на Python.

  • Программирование или скриптинг?
  • Как создать скрипт Python
  • Как превратить код Python для Jupyter Notebook в скрипт Python?
  • Создадим скрипт Python
    • Шаг №1 — откройте текстовый редактор.
    • Шаг №2 — скопируйте и вставьте код!
    • Шаг №3 — Сохраните файл как файл .py!
    • Шаг № 4 — Снова откройте текстовый файл
    • Шаг № 5 — Добавьте Shebang!
    • Дополнительно: шаг № 6 — сделать скрипты на Python исполняемыми
    • Шаг №7 — запустите скрипт на Python!
    • Шаг № 8 — почему я ничего не вижу?
    • Шаг № 9 — Вы создали скрипт на Python
  • Заключение

Обработку данных на основе Python можно разбить на маленькие этапы. Например:

  1. Импорт numpy и pandas.
  2. Загрузка необработанных данных из .csv файла в DataFrame.
  3. Загрузка необработанных данных из словаря Python в другой DataFrame.
  4. Объединение двух фреймов данных.
  5. Сортировка значений.
  6. Заполнение пустых значений.
  7. И так далее…

Можно выполнить эти задачи вручную. Или поместить эти команды в скрипт Python. Это и есть скриптинг.

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

Вы можете использовать любой код, написанный ранее в Jupyter. Например, вот мой Jupyter Notebook.

Как создать скрипт Python

Для этого нужно скопировать все строки из Jupyter Notebook и поместить их в текстовый редактор. После чего сохранить в файл с расширением .py.

Если вы находитесь на удаленном сервере, откройте свой любимый текстовый редактор. Для этого введите команду:

Шаг №1 - откройте текстовый редактор.

Вы можете использовать любой текстовый редактор (vim, nano и т. д.).
Но если вы хотите что-то более продвинутое, я настоятельно рекомендую Sublime Text 3.

Шаг №1 - откройте текстовый редактор. - 2

Скопируйте и вставьте весь код из Jupyter Notebook в текстовый редактор:

Шаг №2 - скопируйте и вставьте код!

Нажмите кнопку 10-Quit в правом нижнем углу (или Esc+0 на клавиатуре).

Шаг №3 - Сохраните файл как файл .py!

После чего mcedit спросит, хотите ли вы сохранить файл? Нажмите: Yes! Затем задайте имя новому текстовому файлу. Скрипты Python имеют собственное расширение: .py.

Шаг №3 - Сохраните файл как файл .py! - 2

Нажмите ОК. Теперь текстовый файл теперь стал скриптом Python.

Вернемся к редактированию файла, набрав команду:

Теперь код выглядит более похожим на Python с различной подсветкой:

Шаг № 4 - Снова откройте текстовый файл

Это потому, что вы добавили расширение .py. В результате этого редактор mcedit распознал текстовый файл как скрипт Python.

Shebang — это строка кода, которую нужно поместить в самом начале скрипта. Его задача – сообщить ОС, что у вас есть исполняемый файл Python3.

Строка shebang для скриптов Python3 выглядит следующим образом:

#! / usr / bin / env python3

Шаг № 5 - Добавьте Shebang!

Добавленный Shebang

Если честно, ваш скрипт будет работать и без него. Несмотря на это, я предпочитаю добавлять Shebang по нескольким причинам:

  • В среде разработки, в которой доступно сразу несколько версий Python, Shebang прояснит, какой интерпретатор должен выполнить скрипт.
  • Когда один из ваших коллег откроет скрипт, он сразу увидит, на каком языке он написан.

После добавления Shebang, снова сохраните файл и попробуйте запустить скрипт, введя команду:

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

demoscript.py: Permission denied

В Python подобная ошибка прав доступа не возникает. Если вы не столкнулись с этой проблемой, просто перейдите к шагу № 7.

Если у вас возникла ошибка прав доступа, в командной строке введите этот код:

sudo chmod 777 demoscript.py

Дополнительно: шаг № 6 - сделать скрипты на Python исполняемыми

Затем введите свой пароль.

Запустите скрипт, введя команду:

Шаг №7 - запустите скрипт на Python!

Это означает, что ваш скрипт на Python запущен… Но вы не видите никакого результата на экране.

В большинстве случаев, когда вы конвертируете проект Jupyter Notebook в скрипт Python, вы не увидите на экране ничего. Это потому, что последняя строка вашего кода была такой:

Шаг № 8 - почему я ничего не вижу?

Вернитесь к своему скрипту и измените последнюю строку на эту:

Шаг № 8 - почему я ничего не вижу? - 2

Нажмите 10-Quit и Save.

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

Победа!

Шаг № 9 - Вы создали скрипт на Python

Вы создали скрипт на Python, и он работает. Но вы все равно захотите использовать Jupyter Notebook. Так как он является идеальным инструментом для тестирования и настройки процессов. Поэтому:

  1. Я создаю прототип проекта на Python в Jupyter Notebook. Затем создаю код и выясняю, какие шаги необходимы.
  2. Затем удаляю ненужные фрагменты кода и импортированные пакеты, сортирую задачи Python в порядке их выполнения.
  3. Добавляю комментарии к коду.
  4. Перемещаю все в текстовый редактор (Sublime Text или mcedit) и создаю скрипт Python, который можно автоматизировать.

Написание и запуск скриптов Python это не магия. Если вы знаете, как писать код на Python, то сможете освоить и скрипты

Все курсы > Программирование на Питоне > Занятие 13

Сегодня мы сделаем шаг назад и посмотрим в целом, что такое программа на Питоне.

Способ 1. Писать код в облаке в Google Colab.

Способ 2. Написать программу в отдельном файле (скрипте) с расширением .py и передать этот код специальному интерпретатору для исполнения.

Способ 3. Установить Jupyter Notebook (локальный аналог Google Colab).

программа на Питоне, способы исполнения кода

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

Кроме того, мы рассмотрим возможности по созданию собственных модулей и пакетов в Питоне.

Установка Питона на Windows

Прежде чем мы начнем писать программу, нам нужно установить библиотеки (libraries) и интерпретатор (interpreter) для обработки кода.

Шаг 1. Проверить, установлен ли Питон на вашем компьютере

Для этого вначале нажмите клавишу Windows и клавишу R на клавиатуре.

клавиши Windows + R

В появившемся окне «Выполнить» введите
cmd и нажмите Enter.

окно "Выполнить" в Windows

Появится так называемая «командная строка» (Command Line Promt) — отдельная программа, позволяющая взаимодействовать с Windows не графически (как мы привыкли делать), а через текстовые команды.

командная строка (Command Line Promt)

Теперь введите
python —version. Если Питон установлен, то программа сообщит текущую версию. В противном случае появится вот такая запись.

проверка, установлен ли Питон

Если Питон не установлен, переходите к шагу 2. В случае если вы его уже установили, переходите сразу к шагу 3.

Шаг 2. Скачать Питон с официального сайта

Перейдем на сайт www.python.org/dowloads/⧉ и скачаем, среди прочего, базовый функционал Питона, а также интерпретатор для Windows, который позволит нам исполнять написанный нами код.

скачивание Питона с официального сайта

После скачивания и запуска файла откроется мастер установки.

добавление Питона в переменную PATH

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

Снова проверим установку Питона на компьютере, повторив действия Шага 1. В командной строке должна появиться установленная на данный момент версия Питона.

проверка версии Питона

Шаг 3. Запустить Питон из командной строки

Теперь давайте введем в командной строке команду
py. Должны появиться символы
>>>.

запуск Питона из командной строки

Это значит, что командная строка перешла в интерактивный режим, и мы можем писать код на Питоне.

Напишем классическую фразу:

При корректном исполнении кода фраза будет выведена на экран.

написание и исполнение кода на Питоне в интерактивном режиме

Однако, как вы помните, наша задача — исполнить не отдельную команду, а скрипт, то есть целую программу на Питоне, а для этого нам нужно эту программу создать.

Поэтому выйдем из интерактивного режима с помощью команды
quit() или
exit(), закроем окно командной строки и перейдем к созданию программы на Питоне.

Создание программы на Питоне

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

Шаг 1. Скачать редактор кода

Редактор кода — это текстовый редактор, который, среди прочего, правильно подсвечивает код на том языке, на котором вы программируете.

В принципе, если вы работаете на Windows, то можете воспользоваться и «Блокнотом» (Notepad), который уже установлен в этой операционной системе (MS Word использовать не стоит). Достаточно написать в нем код, сохранить файл и изменить расширение с .txt на .py.

Если вы не видите расширения файлов, в «Проводнике» нажмите на вкладку «Вид» и поставьте галочку напротив «Расширения имен файлов».

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

  • Notepad++⧉
  • Sublime⧉
  • Atom⧉

На сегодняшнем занятии мы будем использовать Atom.

Редактор Atom

После установки и запуска редактора Atom закройте ненужные вкладки и нажмите FileNew File.

Затем, чтобы сообщить редактору, что мы хотим писать код на Питоне, сохраним этот файл с расширением .py. Для этого нажмем FileSave As и сохраним файл, например, под именем script.py на Рабочий стол.

интерфейс редактора Atom

Благодаря расширению .py Atom будет знать, что в файле script.py мы собираемся писать код на Питоне.

Шаг 2. Написать программу на Питоне

Первой программой будет алгоритм линейного поиска (linear search algorithm). Этот алгоритм проверяет наличие числа в массиве путем простого перебора всех значений от первого до последнего.

алгоритм линейного поиска

Напишем такую программу в редакторе Atom и сохраним файл script.py.

# возьмем массив,

arr = [3, 7, 0, 2, 5]

# в котором нам нужно найти число 2

x = 2

# в цикле пройдемся по индексу массива

for i in range(len(arr)):

    # если искомое число находится на этом индексе

    if (arr[i] == x):

        # выведем индекс

        print(i)

Если у вас не получилось создать файл в редакторе Atom, вы можете его скачать.

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

Шаг 3. Запустить программу из командной строки

Запустим этот код с помощью командной строки.

  1. Откроем командную строку через клавиши Window + R
    cmd. Перейдем на Рабочий стол (напомню, файл script.py мы сохранили именно туда) с помощью команды
    cd Desktop.

Команда cd (change directory) позволяет перейти в другую папку, а Desktop — это Рабочий стол, то есть название той папки, куда мы хотим перейти. В результате командная строка должна выглядеть вот так:

смена папки в командной строке

  1. Теперь просто введите script.py. Так мы вызовем интерпретатор и исполним код.

исполнение программы на Питоне в командной строке

Все, наша первая программа на Питоне готова.

Установка библиотек

Как уже было сказано, по умолчанию, с сайта www.python.org устанавливается лишь базовый функционал. Если мы хотим использовать, например, библиотеку Numpy или библиотеку Matplotlib нам нужно установить их отдельно. В этом нам поможет программа pip.

Программа pip

pip — это программа, которая помогает устанавливать (обновлять и удалять) дополнительные библиотеки на вашем компьютере. По сути эта программа связывается с репозиторием (хранилищем) пакетов/библиотек Python Package Index или PyPI (pypi.org⧉) и скачивает запрашиваемые файлы.

Все действия осуществляются из командной строки.

Если вы устанавливали Питон в соответствии с приведенной выше инструкцией, то pip уже присутствует на вашем компьютере. Проверить это можно с помощью команды
pip —version.

проверка версии программы pip

Кроме того, мы можем посмотреть на список всех установленных на компьютере библиотек через команду
pip list.

список установленных библиотек Питона

Установка библиотеки Numpy через pip install

Установим библиотеку Numpy. Для этого введем в командной строке
pip install numpy.

установка Numpy через pip

Проверить установку отдельного пакета можно с помощью команды
pip show numpy.

проверка версии Numpy

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

Теперь мы можем использовать установленную библиотеку Numpy внутри командной строки. Вначале перейдем в интерактивный режим с помощью команды py. После этого построчно (каждый раз нажимая Enter) введем следующие команды:

import numpy as np

arr=np.array([1, 2, 3])

type(arr)

использование установленной через pip библиотеки

Как мы видим, в результате исполнения этого кода Питон успешно создал массив Numpy.

Обновление и удаление библиотек

Создатели библиотек периодически вносят в них обновления, и эти обновления полезно скачивать на свой компьютер. Воспользуйтесь следующей командой:
pip install —upgrade numpy.

обновление библиотек через pip

Для удаления пакета введите команду
pip uninstall numpy.

удаление библиотек через pip

В процессе удаления будет нужно нажать Y + Enter для подтверждения операции. Другие библиотеки устанавливаются, обновляются и удаляются точно так же.

Модуль в Питоне

Помимо использования Питона в интерактивном режиме и запуска кода из файла мы можем создавать собственные модули.

Модуль в Питоне — это программа на Питоне (файл с расширением .py), которую мы можем использовать в других программах с помощью команды import.

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

Создание собственного модуля

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

Алгоритм линейного поиска

Алгоритм линейного поиска у нас уже готов. Достаточно «обернуть» его в функцию.

# объявим функцию linear()

def linear(arr, x):

    for i in range(len(arr)):

        if arr[i] == x:

            return i

Теперь перейдем к бинарному поиску.

Алгоритм бинарного поиска

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

телефонная книга

Если фамилия этого человека начинается с буквы А, то мы довольно быстро найдем его номер, используя уже известный нам алгоритм линейного поиска. А если он Яковлев? Линейному поиску придется перебрать все буквы от А до Я.

Бинарный же поиск действует иначе. Вначале мы открываем книгу посередине, скажем, на букве П.

алгоритм бинарного поиска: поиск по словарю

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

алгоритм бинарного поиска: поиск по словарю 2

Так мы будем действовать до тех пор, пока не найдем нужную нам букву.

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

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

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

# создадим класс BinarySearch

class BinarySearch:

    # метод __init__() пропишем, но оставим пустым

    def __init__(self):

        pass

    # метод .srt() будет сортировать список чисел

    def srt(self, arr):

        # для этого мы используем функцию sorted()

        arr = sorted(arr)

        return arr

    # сам бинарный поиск будет выполняться через метод .check()

    def check(self, arr, x):

        # вначале зададим индексы первого и последнего значений

        # отсортированного списка

        low, high = 0, len(arr)1

        # цикл while будет длиться до тех пор, пока индекс последнего значения

        # больше или равен первому

        while low <= high:

            # найдем индекс среднего значения списка

            mid = low + (high low) // 2

            # если число с этим индексом равно искомому,

            if arr[mid] == x:

                # вернем этот индекс

                return mid

            # если меньше искомого (число «справа» от середины)

            elif arr[mid] < x:

                # новым нижним индексом будет «середина + 1»

                low = mid + 1

            # если больше искомого (число «слева» от середины)

            else:

                # новым верхним индексом будет «середина — 1»

                high = mid 1

        # если число так и не найдено, вернем -1

        mid = 1

        return mid

Хотя это уводит нас в сторону от темы сегодняшнего занятия, поясню код нахождения индекса среднего значения списка.

mid = low + (high low) // 2

На первый взгляд индекс среднего значения можно найти вот так

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

Также замечу, что мы используем оператор целочисленного деления
//, потому что в Питоне результатом обычного деления является число с плавающей точкой (float). Индекс же таким числом быть не может.

Полностью код для обоих алгоритмов будет выглядеть следующим образом.

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

def linear(arr, x):

    for i in range(len(arr)):

        if arr[i] == x:

            return i

class BinarySearch:

    def __init__(self):

        pass

    def srt(self, arr):

        arr = sorted(arr)

        return arr

    def check(self, arr, x):

        low, high = 0, len(arr)1

        while low <= high:

            mid = low + (high low) // 2

            if arr[mid] == x:

                return mid

            elif arr[mid] < x:

                low = mid + 1

            else:

                high = mid 1

        mid = 1

        return mid

Документирование кода с помощью docstrings

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

Одновременно в Питоне существуют так называемые строки документации (docstrings). Они используются для описания работы функции, метода, класса или модуля. Доступ к ним можно получить через атрибут __doc__ или функцию help().

В чем основные особенности создания docstrings?

  • Docstrings заключаются в тройные одинарные или двойные кавычки
  • Их следует располагать сразу после объявления функции, метода, класса или модуля

Добавим соответствующие docstrings в только что созданный нами модуль и параллельно разберем основные принципы написания документации. Начнем с модуля в целом.

Строки документации для модуля в Питоне

Документация модуля описывает модуль и перечисляет все доступные функции и классы. Например, для модуля mymodule документация могла бы выглядеть следующим образом.

«»»

Модуль для поиска элементов в массиве чисел.

============================================

Classes

——-

BinarySearch

Functions

———

linear

«»»

Строки документации для функции описывают саму функцию, параметры и возвращаемое значение. Напишем документацию к функции linear().

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

def linear(arr, x):

    «»»Выполняет линейный поиск по массиву чисел.

    Parameters

    ———-

    arr : {list, ndarray}

        Массив чисел, по которому выполняется поиск.

    x : int

        Искомое число.

    Returns

    ——-

    i : int

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

    «»»

    for i in range(len(arr)):

        if arr[i] == x:

            return i

Строк документации для класса описывают сам класс, а также перечисляют доступные атрибуты и методы. Каждый метод внутри класса сопровождается отдельной документацией.

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

58

59

60

61

class BinarySearch:

    «»»Бинарный поиск по массиву чисел.

    «»»

    def __init__(self):

        pass

    def srt(self, arr):

        «»»Сортирует массив чисел в возрастающем порядке.

        Parameters

        ———-

        arr : {list, ndarray}

            Массив для сортировки.

        Returns

        ——-

        arr : {list, ndarray}

            Массив, отсортированный в возрастающем порядке.

        «»»

        arr = sorted(arr)

        return arr

    def check(self, arr, x):

        «»»Проверяет наличие числа в массиве c помощью алгоритма бинарного поиска.

        Parameters

        ———-

        arr : {list, numpy array}

            Массив чисел, по которому выполняется поиск.

        x : int

            Искомое число.

        Returns

        ——-

        mid : int

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

            Возвращает -1, если число не найдено.

        «»»

        low, high = 0, len(arr)1

        while low <= high:

            mid = low + (high low) // 2

            if arr[mid] == x:

                return mid

            elif arr[mid] < x:

                low = mid + 1

            else:

                high = mid 1

        mid = 1

        return mid

Полностью снабженный документацией модуль выглядит следующим образом.

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

58

59

60

61

62

63

64

65

66

67

68

69

70

71

72

73

74

75

76

77

78

79

80

81

82

83

84

85

86

87

88

89

90

91

92

93

94

95

96

97

98

«»»

Модуль для поиска элементов в массиве чисел.

============================================

Classes

——-

BinarySearch

Functions

———

linear

«»»

def linear(arr, x):

    «»»Выполняет линейный поиск по массиву чисел.

    Parameters

    ———-

    arr : {list, ndarray}

        Массив чисел, по которому выполняется поиск.

    x : int

        Искомое число.

    Returns

    ——-

    i : int

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

    «»»

    for i in range(len(arr)):

        if arr[i] == x:

            return i

class BinarySearch:

    «»»Бинарный поиск по массиву чисел.

    «»»

    def __init__(self):

        pass

    def srt(self, arr):

        «»»Сортирует массив чисел в возрастающем порядке.

        Parameters

        ———-

        arr : {list, ndarray}

            Массив для сортировки.

        Returns

        ——-

        arr : {list, ndarray}

            Массив, отсортированный в возрастающем порядке.

        «»»

        arr = sorted(arr)

        return arr

    def check(self, arr, x):

        «»»Проверяет наличие числа в массиве c помощью алгоритма бинарного поиска.

        Parameters

        ———-

        arr : {list, numpy array}

            Массив чисел, по которому выполняется поиск.

        x : int

            Искомое число.

        Returns

        ——-

        mid : int

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

            Возвращает -1, если число не найдено.

        «»»

        low, high = 0, len(arr)1

        while low <= high:

            mid = low + (high low) // 2

            if arr[mid] == x:

                return mid

            elif arr[mid] < x:

                low = mid + 1

            else:

                high = mid 1

        mid = 1

        return mid

Замечу, что в данном случае мы использовали стиль документирования Numpy (NumPy documentation style). Он используется во многих известных пакетах: NumPy, SciPy, Pandas или, например, Scikit-Learn. При этом существуют и другие стили документирования.

Сохраним этот файл под именем mymodule.py. Все, наш модуль готов. Если у вас не получилось создать этот файл, вы можете скачать его по ссылке ниже.

Создание документации с помощью Pyment

Дополнительно замечу, что шаблон или «каркас» документации можно создать с помощью специального пакета Pyment. Для этого:

  1. Скачайте пакет Pyment через
    pip install pyment
  2. Убедитесь, что командная строка указывает на ту папку, в которой находится ваш модуль mymodule.py (например, на Рабочий стол)
  3. Введите команду
    pyment -w -o numpydoc mymodule.py. В данном случае вы буквально просите pyment создать документацию в стиле Numpy в файле под названием mymodule.py
  4. Откройте файл в редакторе кода и начинайте заполнять шаблон.

Загрузка и импорт модуля в Google Colab

Откроем ноутбук к этому занятию⧉

Давайте подгрузим файл mymodule.py в сессионное хранилище Google Colab.

подгрузка собственного модуля на Питоне в Google Colab

Теперь мы можем работать с этим модулем так, как мы работали с функциями модуля random или классами библиотеки sklearn.

Вначале импортируем функцию linear() из модуля mymodule.

from mymodule import linear

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

arr = [3, 7, 0, 2, 5]

target = 2

Вызовем функцию linear() и передадим ей список и целевое значение в качестве аргументов.

Теперь возьмем список большего размера и другое целевое значение.

arr = [9, 3, 343, 5, 8, 1, 20111, 32, 11, 6, 4]

target = 9

Импортируем модуль mymodule под псевдонимом mm.

Воспользуемся бинарным поиском. Для этого вначале создадим объект класса BinarySearch и поместим его в переменную src.

Прежде чем выполнить поиск нам необходимо отсортировать список чисел. Вызовем метод .srt() класса BinarySearch.

# передадим методу .srt() список arr для сортировки

sorted_arr = srch.srt(arr)

# посмотрим на результат

sorted_arr

[1, 3, 4, 5, 6, 8, 9, 11, 32, 343, 20111]

Теперь воспользуемся методом .check(), чтобы проверить, присутствует ли в списке число девять.

# напомню, что индекс числа 9 мы будем отсчитывать с нуля

src.check(sorted_arr, target)

В отсортированном списке это число присутствует под индексом шесть.

Просмотр документации модуля

Вначале выведем документацию модуля в целом.

Модуль для поиска элементов в массиве чисел.

============================================

Classes

——-

BinarySearch

Functions

———

linear

Посмотрим на функию linear().

Выполняет линейный поиск по массиву чисел.

    Parameters

    ———-

    arr : {list, ndarray}

        Массив чисел, по которому выполняется поиск.

    x : int

        Искомое число.

    Returns

    ——-

    i : int

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

И класс BinarySearch.

print(mm.BinarySearch.__doc__)

Бинарный поиск по массиву чисел.

Мы также можем посмотреть документацию отдельного метода внутри класса.

print(mm.BinarySearch.srt.__doc__)

Сортирует массив чисел в возрастающем порядке.

        Parameters

        

        arr : {list, ndarray}

            Массив для сортировки.

        Returns

        

        arr : {list, ndarray}

            Массив, отсортированный в возрастающем порядке.

Напомню, что документацию можно также посмотреть с помощью функции help().

Импорт собственного модуля в командной строке

Модуль в Питоне не обязательно подгружать в Google Colab, его также можно импортировать локально в командной строке.

Когда в интерактивном режиме мы пытаемся импортировать модуль с помощью команды import, Питон начинает искать этот модуль в конкретных папках. Посмотреть, что это за папки можно с помощью встроенного в базовый функционал модуля sys. В интерактивном режиме (команда
py) последовательно введите следующие команды.

содержание переменной sys.path

Обратите внимание, что первой в списке
[»] указана текущая папка.

Если ваш модуль не находится в одной из этих папок, импортировать его не получится. Здесь есть два варианта: либо переместить файл в одну из указанных папок, либо добавить новую папку в переменную path.

Способ 1. Переместить файл в папку из списка

Текущая папка будет иметь адрес, похожий на
C:Usersuser (замените user на имя вашей учетной записи). Введите этот адрес в Проводнике.

ввод адреса в Проводнике на Windows

Переместите туда наш модуль mymodule.py. Теперь войдем в интерактивный режим (команда
py) и импортируем модуль с помощью команды
import. После этого создадим массив, целевую переменную и вызовем функцию linear().

import mymodule

arr = [3, 7, 0, 2, 5]

target = 2

mymodule.linear(arr, target)

импорт модуля на Питоне в интерактивном режиме из командной строки

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

Способ 2. Добавить новый путь (папку) в переменную path

Добавим Рабочий стол в список sys.path. Для этого прекрасно подойдет метод .append(), который мы использовали для обычных питоновских списков.

Например, добавим Desktop (Рабочий стол).

добавление папки в переменную sys.path

Не забудьте заменить user на имя пользователя на вашем компьютере, а также обратите внимание на двойные обратные косые черты
в абсолютном пути к папке Desktop.

содержание переменной sys.path после добавления папки

Мы готовы импортировать наш модуль с Рабочего стола. Вернем файл mymodule.py на Рабочий стол, войдем в интерактивный режим (команда
py и последовательно введем код ниже.

import mymodule

arr = [3, 7, 0, 2, 5]

target = 2

mymodule.linear(arr, target)

импорт модуля из добавленной в sys.path папки

Нам снова удалось импортировать необходимую нам функцию linear().

Интерпретация и компиляция

Небольшое отступление от темы занятия. В самом начале мы сказали, что вместе с базовым функционалом Питона мы импортируем еще и интерпретатор. Давайте, разберемся, что это такое.

Как вы помните, компьютер понимает только нули и единицы, но никак не код на Питоне. Перевести понятный человеку язык программирования на машинный можно двумя способами: через компилятор (compiler) и через интерпретатор (interpreter).

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

Компилятор

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

Компилятор берет файл с понятным человеку исходным кодом, переводит его в нули и единицы и сохраняет получившийся машинный код в исполняемом (executable) файле (на Windows — это файл с расширением .exe).

компилятор

После этого мы можем запустить файл .exe и увидеть результат работы программы.

Интерпретатор

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

интерпретатор

Другими словами, интерпретатор — это программа, которая позволяет обрабатывать код и сразу выдавать результат.

Как следствие, языки делятся на компилируемые и интерпретируемые. Питон относится к интерпретируемым языкам, а, например, С — к компилируемым.

Впрочем, программа на Питоне может быть скомпилирована, например, с помощью пакета PyInstaller.

Кроме того, возможно вы обратили внимание, что когда мы вызывали модуль mymodule в командной строке, то Питон автоматически создал папку под названием __pycache__.pyc. В ней содержится скомпилированный байт-код программы (промежуточный код между Питоном и машинным языком), который ускоряет последующий запуск нашего модуля.

Пакет в Питоне

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

программа на Питоне (скрипт) - модуль - пакет

Примечание. Некоторые пакеты (например, Numpy или Pandas) принято называть библиотеками. При этом с технической точки зрения пакет и библиотека — это одно и то же.

Создание собственного пакета

В качестве упражнения создадим несложный пакет на Питоне и поместим его в тестовый репозиторий TestPyPI. Это своего рода «песочница», в которой можно научиться создавать пакеты перед их загрузкой в «большой» репозиторий PyPI.

Обратите внимание, PyPI и TestPyPI — это разные сайты, для которых требуются разные учетные записи.

Добавлю, что по большей части этот раздел создан на основе примера, приведенного в документации Питона⧉.

Шаг 1. Создание учетной записи

В первую очередь зарегистрируйтесь на сайте https://test.pypi.org/⧉.

Шаг 2. Создание файлов

Теперь создайте пакет example_package (по сути, набор папок и файлов) со следующей структурой.

base/

└── src/

    └── example_package/

        ├── __init__.py

        └── example_module.py

В пакет мы поместим модуль example_module.py. В модуле объявим функцию для возведения числа в квадрат square().

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

«»»

Модуль для выполнения арифметических операций.

============================================

Functions

———

square

«»»

def square(number):

    «»»Возводит число в квадрат.

    Parameters

    ———-      

    number : int

        Возводимое во вторую степень число.

    Returns

    ——-

    int

        Квадрат числа.

    «»»

    return number ** 2

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

Все последующие инструкции в командной строке будут выполняться из папки base/.

Например, если папка base/ находится на Рабочем столе, то перейти в нее можно с помощью команды
cd Desktopbase.

переход в папку base в командной строке

Дополнительные файлы

Теперь давайте немного усложним структуру и добавим новые файлы.

base/

├── LICENSE.txt

├── pyproject.toml

├── README.md

├── setup.py

└── src/

    └── example_package/

        ├── __init__.py

        └── example_module.py

  1. В файл pyproject.toml поместим следующий код:

[build-system]

requires = [«setuptools>=42»]

build-backend = «setuptools.build_meta»

build-system.requires указывает на пакеты, необходимые для создания дистрибутива (то есть готового к распротранению пакета),
build-system.build-backend прописывает, какой объект будет использован для его создания.

  1. В setuptools.py содержится информация о пакете. Там же прописывается, какие файлы следует использовать при создании дистрибутива.

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

import setuptools

with open(«README.md», «r», encoding=«utf-8») as fh:

    long_description = fh.read()

setuptools.setup(

    name=«example-package-DmitryMakarov»,

    version=«0.0.1»,

    author=«Dmitry Makarov»,

    author_email=«dm.v.makarov@gmail.com»,

    description=«Simple arithmetic package»,

    long_description=long_description,

    long_description_content_type=«text/markdown»,

    url=«https://github.com»,

    project_urls={

        «Bug Tracker»: «https://github.com»,

    },

    classifiers=[

        «Programming Language :: Python :: 3»,

        «License :: OSI Approved :: MIT License»,

        «Operating System :: OS Independent»,

    ],

    package_dir={«»: «src»},

    packages=setuptools.find_packages(where=«src»),

    python_requires=«>=3.6»,

)

Вначале мы импортируем пакет setuptools. После этого открываем файл README.md и помещаем его содержимое в переменную longdescription.

Затем вызываем функцию setuptools.setup() и передаем ей целый ряд параметров. При создании собственного пакета замените значения следующих параметров:

  • Название пакета (name). Оно должно быть уникальным. Для того чтобы обеспечить уникальность названия, проще всего добавить к нему свой логин на сайте https://test.pypi.org/ в формате «название-пакета-логин».
  • Также вы можете заменить поля author и author_email.

Менять остальные поля, в принципе, не обязательно.

  1. Файл README.md

В файле README.md содержатся описание пакета, примеры и технические детали проекта. Расширение .md указывает на то, что этот файл сохранен в формате markdown и поддерживает форматирование текста.

В документации на сайте www.markdownguide.org⧉ вы найдете рекомендации по использованию языка markdown.

В нашем файле мы напишем следующий текст.

# Тестовый пакет

Файл README.md может содержать описание, примеры и технические детали пакета.

Формат .md (markdown) поддерживает форматирование текста. Например, **полужирный шрифт** или *курсив*. Более полный перечень можно найти по [ссылке](https://guides.github.com/features/mastering-markdown/)

  1. Файл LICENSE.txt

Остается создать файл с лицензией LICENSE.txt. Мы будем использовать лицензию открытого и свободного программного обеспечения MIT (Массачусетского технологического института).

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

MIT License

Copyright (c) 2022 Dmitry Makarov

Permission is hereby granted, free of charge, to any person obtaining a copy

of this software and associated documentation files (the «Software»), to deal

in the Software without restriction, including without limitation the rights

to use, copy, modify, merge, publish, distribute, sublicense, and/or sell

copies of the Software, and to permit persons to whom the Software is

furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all

copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED «AS IS», WITHOUT WARRANTY OF ANY KIND, EXPRESS OR

IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,

FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE

AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER

LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,

OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE

SOFTWARE.

Шаг 3. Создание дистрибутива

Скачаем инструменты, необходимые для создания дистрибутива.

Теперь из папки base/ введите команду
py -m build. После ее выполнения должно появиться уведомление об успешном создании дистрибутива пакета.

создание дистрибутива собственного тестового пакета на Питоне

Сам дистрибутив появится в папке base/.

дистрибутив тестового пакета

Шаг 4. Подгрузка дистрибутива

Скачаем инструмент для подгрузки twine.

И выполним подгрузку посредством следующей команды

py -m twine upload —repository testpypi dist/*

Пароль при вводе отображаться не будет (ни в явном, ни в скрытом виде). Просто введите нужные символы и нажмите Enter.

Должен появиться вот такой результат.

подгрузка собственного пакета на TestPyPI

Как вы видите, подгруженный пакет доступен по адресу: https://test.pypi.org/project/example-package-DmitryMakarov/0.0.1/⧉. Мы создали свой первый пакет.

Установка и использование пакета

Если вы захотите воспользоваться этим пакетом, то в командной строке введите команду, которая представлена на первой странице пакета.

страница тестового пакета на Test.PyPI.org

pip install -i https://test.pypi.org/simple/ example-package-DmitryMakarov==0.0.1

Результат исполнения этой команды вы видите ниже.

установка собственного тестового пакета через pip

Теперь мы можем пользоваться нашим пакетом. В интерактивном режиме (команду py) импортируем модуль example_module из пакета example_package и вызовем функцию square(), передав ей, например, число два.

from example_package import example_module

example_module.square(2)

использование пакета, установленного из TestPyPI

В целом создание «взрослого» пакета на PyPI следует похожей схеме.

Подведем итог

Сегодня мы расширили наше представление о том, как запускать код на Питоне. Если раньше мы использовали только Google Colab, то теперь можем создавать собственные программы, модули и пакеты.

Вопросы для закрепления

Вопрос. Чем программа (скрипт) отличается от модуля?

Посмотреть правильный ответ

Ответ: технически и то, и другое — файл с расширением .py, при этом скрипт не предполагает его использования в других программах, а модуль предназначен именно для этого.

Вопрос. Зачем добавлять Питон в переменнаую окружения PATH в ОС Windows?

Посмотреть правильный ответ

Ответ: мы добавляем Питон в переменную PATH ОС Windows, чтобы в командной строке мы могли исполнять Питон в интерактивном режиме.

Вопрос. Что такое переменная path модуля sys в Питоне?

Посмотреть правильный ответ

Ответ: в переменной path модуля sys указаны те папки компьютера, в которых интерпретатор Питона будет искать файл для его импорта. Эта переменная отличается от переменной PATH в операционной системе.


Ответы на вопросы

Вопрос. Что такое
if __name__ == ‘__main__’:?

Ответ. Перед тем как исполнить код (например, в командной строке), интерпретатор Питона объявляет несколько переменных. Одна из них называется
__name__. Этой переменной присваивается значение __main__. Создадим файл script.py со следующим кодом и запустим его в командной строке.

значение переменной __name__ при исполнении кода напрямую

Теперь создадим еще один файл и назовем его module.py. Если вызвать его напрямую, то разумеется переменная
__name__ также будет иметь значение __main__.

При этом если импортировать файл module.py внутри script.py, то значение переменной
__name__ файла module.py изменится на его название (то есть слово module). Создадим файл module.py со следующим кодом.

Заменим код в файле script.py и исполним его.

import module

print(__name__)

значение переменной __name__ при исполнении импортированного файла

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

Как мы получили такой результат? Сначала был импортирован код из файла module.py, внутри которого переменной
__name__ было присвоено значение module. Именно это значение мы видим на первой строке вывода. Затем было выведено значение переменной
__name__ файла script.py (то есть __main__).

Теперь давайте изменим код файла module.py.

if __name__ == ‘__main__’:

    print(‘This runs as the main file’)

else:

    print(‘This runs as an imported file’)

(1) Запустим его как основной файл напрямую из командной строки.

if __name__ == '__main__'

(2) Теперь импортируем его в script.py (код файла module.py оставим без изменений).

if __name__ == '__main__' внутри импортированного файла

Как вы видите, в импортированном файле module.py переменная
__name__ не содержит значения __main__, поэтому исполнилось выражение после else. В script.py переменная
__name__ по-прежнему имеет значение __main__.

Зачем может быть нужно такое условие? Если вы пишете код, который в первую очередь предназначен для импорта (то есть модуль), будет разумно не вызывать содержащиеся в нем функции автоматически. В этом случае вызов функций можно заключить в обсуждаемое условие.

Изменим файл module.py.

def foo():

    print(‘This is an imported function’)

if __name__ == ‘__main__’:

    foo()

Теперь внутри script.py вначале просто импортируем файл module.py.

функция с условием if __name__ == '__main__'

При вызове модуля ничего не произошло. Так и должно быть. Для того чтобы вызвать функцию foo() нам нужно обратиться к ней напрямую. Изменим файл script.py и исполним его.

import module

module.foo()

вызов функции с условием if __name__ == '__main__'

На следующем занятии, как мы и планировали, мы посмотрим, как можно исполнять код на Питоне в программе Jupyter Notebook.

Python — невероятно гибкий язык программирования, который хорошо интегрируется с существующими программами. Немало Python-кода написано в виде скриптов и интерфейсов командной строки (CLI).

Инструменты и интерфейсы командной строки — эффективная вещь, так как они позволяют автоматизировать практически всё что угодно. Как следствие, эти интерфейсы с течением времени могут стать довольно сложными.

Обычно всё начинается с простого скрипта на Python, который что-то делает. Например, получает доступ к веб-API и выводит результат в консоль:

# print_user_agent.py
import requests

json = requests.get('http://httpbin.org/user-agent').json()
print(json['user-agent'])

Вы можете запустить этот скрипт с помощью команды python3 print_user_agent.py, и он выведет имя user-agent, использованного для вызова API.

Как и было сказано, довольно простой скрипт.

Но что делать, когда подобная программа растёт и становится всё более сложной?

Решением этого вопроса мы сегодня и займёмся. Вы узнаете об основах написания интерфейсов командной строки на Python и о том, как click позволяет упростить этот процесс.

Используя эти знания, мы шаг за шагом перейдём от простого скрипта к интерфейсу командной строки с аргументами, опциями и полезными инструкциями по использованию. Всё это мы сделаем с помощью библиотеки click.

К концу этой статьи вы будете знать:

  • Почему click — лучшая альтернатива argparse и optparse;
  • Как с его помощью создать простой CLI;
  • Как добавить обязательные аргументы командной строки в ваши скрипты;
  • Как парсить флаги и опции командной строки;
  • Как сделать ваши консольные приложения более удобными, добавив справочный текст.

Вы увидите, как сделать всё это с минимальным количеством шаблонного кода.

Примечание переводчика Код в данной статье написан на Python 3.6, работоспособность на более ранних версиях не гарантируется.

Итак, начнём!

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

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

Здесь приходят на выручку такие модули, как optparse и argparse, которые делают нашу жизнь на порядок проще. Но прежде чем мы с ними познакомимся, давайте разберёмся с терминологией.

Основы интерфейса командной строки

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

В зависимости от сложности CLI обычно есть определённые параметры, которые вы можете передавать скрипту:

  1. Аргумент, который является обязательным параметром. Если его не передать, то CLI вернёт ошибку. Например, в следующей команде click является аргументом: pip install click.
  2. Опция — необязательный параметр, который объединяет имя и значение, например --cache-dir ./my-cache. Вы говорите CLI, что значение ./my-cache должно использоваться как директория для кэша.
  3. Флаг, который включает или выключает определённый сценарий. Вероятно, самым частым является --help. Вы только указываете имя, а CLI самостоятельно интерпретирует значение.

С более сложными CLI, такими как pip или Heroku CLI, вы получаете доступ к набору функций, которые собраны под главной точкой входа. Они обычно называются командами или подкомандами.

Возможно, вы уже использовали CLI, когда устанавливали Python-библиотеку с помощью команды pip install <имя пакета>. Команда install говорит CLI, что вы хотите использовать функцию установки пакета, и даёт вам доступ к параметрам, характерным для этой функции.

Пакеты для работы с командной строкой, доступные в стандартной библиотеке Python 3.x

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

Два наиболее известных пакета для этого — optparse и argparse. Они являются частью стандартной библиотеки Python и добавлены туда по принципу «всё включено».

По большей части они делают одно и то же и работают схожим образом. Главное отличие заключается в том, что optparse не используется начиная с Python 3.2, и argparse считается стандартом для создания CLI в Python.

Вы можете узнать о них больше в документации Python, но, чтобы иметь представление, как выглядит скрипт с argparse, посмотрите на пример ниже:

import argparse

parser = argparse.ArgumentParser(description='Process some integers.')
parser.add_argument('integers', metavar='N', type=int, nargs='+',
                    help='an integer for the accumulator')
parser.add_argument('--sum', dest='accumulate', action='store_const',
                    const=sum, default=max,
                    help='sum the integers (default: find the max)')

args = parser.parse_args()
print(args.accumulate(args.integers))

click против argparse: лучшая альтернатива?

Вероятно, вы смотрите на этот код и думаете: «Что это всё значит?» И это является одной из проблем argparse: код с ним неинтуитивен и сложночитаем.

Поэтому вам может понравиться click.

Click решает ту же проблему, что и optparse и argparse, но немного иначе. Он использует декораторы, поэтому ваши команды должны быть функциями, которые можно обернуть этими декораторами.

С click легко создавать многофункциональный CLI с небольшим количеством кода. И этот код будет легко читаться, даже когда ваш CLI вырастет и станет более сложным.

Пишем простой CLI на Python с помощью click

Вдоволь поговорив о CLI и библиотеках, давайте взглянем на пример, чтобы понять, как написать простой CLI с click. Как и в первом примере, мы создаём простой CLI, который выводит результат в консоль. Это несложно:

# cli.py
import click

@click.command()
def main():
    print("I'm a beautiful CLI ✨")

if __name__ == "__main__":
    main()

Не пугайтесь последних двух строк: это то, как Python запускает функцию main при исполнении файла как скрипта.

Как вы видите, всё, что нам нужно сделать — создать функцию и добавить к ней декоратор @click.command(). Он превращает функцию в команду, которая является главной точкой входа нашего скрипта. Теперь вы можете запустить скрипт через командную строку и увидеть что-то вроде этого:

$ python3 cli.py
I'm a beautiful CLI ✨

Что в click здорово, так это то, что мы получаем некоторые дополнительные возможности просто так. Мы не реализовывали справочную функцию, однако вы можете добавить флаг --help и увидеть базовое сообщение:

$ python3 cli.py --help
Usage: cli.py [OPTIONS]

Options:
  --help  Show this message and exit.

Более реалистичный пример CLI на Python с использованием click

Теперь, когда вы знаете, как click упрощает написание CLI, давайте взглянем на более реалистичный пример. Мы напишем программу, которая позволяет нам взаимодействовать с веб-API.

API, который мы дальше будем использовать, — OpenWeatherMap API. Он предоставляет информацию о текущей погоде, а также прогноз на пять дней для определённого местоположения. Мы начнём с тестового API, который возвращает текущую погоду для места.

Прежде чем мы начнём писать код, давайте познакомимся с API. Для этого можно использовать сервис HTTPie, включая онлайн-терминал.

Давайте посмотрим, что случится, когда мы обратимся к API с Лондоном в качестве местоположения:

$ http --body GET http://samples.openweathermap.org/data/2.5/weather 
  q==London 
  appid==b1b15e88fa797225412429c1c50c122a1
{
    "base": "stations",
    "clouds": {
        "all": 90
    },
    "cod": 200,
    "coord": {
        "lat": 51.51,
        "lon": -0.13
    },
    "dt": 1485789600,
    "id": 2643743,
    "main": {
        "humidity": 81,
        "pressure": 1012,
        "temp": 280.32,
        "temp_max": 281.15,
        "temp_min": 279.15
    },
    "name": "London",
    "sys": {
        "country": "GB",
        "id": 5091,
        "message": 0.0103,
        "sunrise": 1485762037,
        "sunset": 1485794875,
        "type": 1
    },
    "visibility": 10000,
    "weather": [
        {
            "description": "light intensity drizzle",
            "icon": "09d",
            "id": 300,
            "main": "Drizzle"
        }
    ],
    "wind": {
        "deg": 80,
        "speed": 4.1
    }
}

Если вы смущены наличием API-ключа в примере сверху, не переживайте, это тестовый API-ключ, предоставляемый сервисом.

Более важное наблюдение заключается в том, что мы отправляем два параметра (обозначаемые == при использовании HTTPie), чтобы узнать текущую погоду:

  • q — место, в котором мы хотим узнать погоду;
  • appid — наш API-ключ.

Это позволяет нам создать простую реализацию на Python с использованием библиотеки requests (опустим обработку ошибок и неудачных запросов для простоты):

import requests

SAMPLE_API_KEY = 'b1b15e88fa797225412429c1c50c122a1'

def current_weather(location, api_key=SAMPLE_API_KEY):
    url = 'http://samples.openweathermap.org/data/2.5/weather'

    query_params = {
        'q': location,
        'appid': api_key,
    }

    response = requests.get(url, params=query_params)

    return response.json()['weather'][0]['description']

Эта функция делает простой запрос к API, используя два параметра. В качестве обязательного аргумента она принимает location (местоположение), которое должно быть строкой. Также мы можем указать API-ключ, передавая параметр api_key при вызове функции. Это необязательно, так как по умолчанию используется тестовый ключ.

И вот мы видим текущую погоду в Python REPL:

>>> current_weather('London')
'light intensity drizzle'  # впрочем, ничего нового ?

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

Простая функция current_weather позволяет нам создать CLI с местоположением, указанным пользователем. Это должно работать примерно так:

$ python3 cli.py London
The weather in London right now: light intensity drizzle.

Как вы, возможно, догадались, местоположение — это аргумент, поскольку оно является обязательным параметром для нашего погодного CLI.

Как нам сделать это при помощи click? Всё довольно просто, мы используем декоратор под названием argument. Кто бы мог подумать?

Давайте возьмём наш предыдущий пример и слегка изменим его, добавив аргумент location:

@click.command()
@click.argument('location')
def main(location):
    weather = current_weather(location)
    print(f"The weather in {location} right now: {weather}.")

Если этот print выглядит для вас странно, не волнуйтесь — это новый способ форматирования строк в Python 3.6+, который называется f-форматированием.

Как вы видите, всё, что нам нужно сделать, это добавить дополнительный декоратор к нашей функции main и дать ему имя. Click использует имя в качестве имени аргумента, переданного обёрнутой функции.

Примечание переводчика Имя аргумента, переданное click, должно совпадать с именем аргумента в объявлении функции.

В нашем случае значение аргумента командной строки location будет передано функции main в качестве аргумента location. Логично, не так ли?

Также вы можете использовать тире в именах, например api-key, которые click переведёт в snake case для имени аргумента в функции, например main(api_key).

Реализация main просто использует нашу функцию current_weather для получения погоды в указанном месте. И затем мы с помощью print выводим полученную информацию.

Готово!

Парсим опциональные параметры с click

Как вы, возможно, догадались, тестовый API ограничивает нас в возможностях. Поэтому, прежде чем мы продолжим, зарегистрируйтесь и получите настоящий API-ключ.

Первое, что нам нужно изменить, — URL, откуда берутся данные о текущей погоде. Это можно сделать, изменив значение переменной url в функции current_weather на URL, указанный в документации OpenWeatherMap:

def current_weather(location, api_key=SAMPLE_API_KEY):
    url = 'https://api.openweathermap.org/data/2.5/weather'

    # дальше всё остаётся как было
    ...

Это изменение приведёт к неработоспособности нашего CLI, так как указанный API-ключ не работает с реальным API. Поэтому давайте добавим новый параметр в наш CLI, который позволит нам указывать API-ключ. Но сначала мы должны решить, будет ли этот параметр аргументом или опцией. Мы сделаем его опцией, так как добавление параметра вроде --api-key делает его более явным и говорящим за себя.
Мы хотим, чтобы наша программа запускалась таким образом:

$ python3 cli.py --api-key  London
The weather in London right now: light intensity drizzle.

Проще простого. Посмотрим, как добавить опцию к нашей существующей команде:

@click.command()
@click.argument('location')
@click.option('--api-key', '-a')
def main(location, api_key):
    weather = current_weather(location, api_key)
    print(f"The weather in {location} right now: {weather}.")

И снова мы добавляем декоратор к нашей функции main. В этот раз мы используем декоратор с говорящим именем @click.option и указываем имя для нашей опции, начинающееся с двух тире. Как вы видите, мы также можем указать сокращение для нашей опции с одним тире, чтобы сэкономить пользователю немного времени.

Как было сказано ранее, click создаёт аргумент для передачи в функцию main из длинного варианта имени. В случае с опцией он убирает впередистоящие тире и переводит её в snake case. Таким образом, --api-key становится api_key.

Чтобы всё заработало, осталось лишь передать API-ключ в функцию current_weather.

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

$ python3 cli.py --api-key  Canmore
The weather in Canmore right now: broken clouds.

Добавляем автоматически генерируемые инструкции по использованию

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

Сначала давайте проверим, что выведет флаг --help после всех сделанных изменений. Довольно неплохо, учитывая что мы не приложили к этому никаких усилий:

$ python3 cli.py --help
Usage: cli.py [OPTIONS] LOCATION

Options:
  -a, --api-key TEXT
  --help              Show this message and exit.

Первое, что нужно исправить, это добавить описание для нашей опции с API-ключом. Всё, что нам для этого нужно сделать, — добавить справочный текст в декоратор @click.option:

@click.command()
@click.argument('location')
@click.option(
    '--api-key', '-a',
    help='your API key for the OpenWeatherMap API',
)
def main(location, api_key):
    ...

Второе (и последнее), что мы сделаем, — добавим документацию для всей click-команды. Самый простой и самый питонический способ сделать это — добавить строку документации в нашу функцию main. Да, нам в любом случае нужно сделать это, поэтому это не лишняя работа:

...
def main(location, api_key):
    """
    A little weather tool that shows you the current weather in a LOCATION of
    your choice. Provide the city name and optionally a two-digit country code.
    Here are two examples:

    1. London,UK

    2. Canmore

    You need a valid API key from OpenWeatherMap for the tool to work. You can
    sign up for a free account at https://openweathermap.org/appid.
    """
    ...

Сложив всё вместе, мы получаем хороший вывод для нашего инструмента:

$ python3 cli.py --help
Usage: cli.py [OPTIONS] LOCATION

  A little weather tool that shows you the current weather in a LOCATION of
  your choice. Provide the city name and optionally a two-digit country
  code. Here are two examples:

  1. London,UK

  2. Canmore

  You need a valid API key from OpenWeatherMap for the tool to work. You can
  sign up for a free account at https://openweathermap.org/appid.

Options:
  -a, --api-key TEXT  your API key for the OpenWeatherMap API
  --help              Show this message and exit.

Подводим итоги

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

import click
import requests

SAMPLE_API_KEY = 'b1b15e88fa797225412429c1c50c122a1'


def current_weather(location, api_key=SAMPLE_API_KEY):
    url = 'https://api.openweathermap.org/data/2.5/weather'

    query_params = {
        'q': location,
        'appid': api_key,
    }

    response = requests.get(url, params=query_params)

    return response.json()['weather'][0]['description']


@click.command()
@click.argument('location')
@click.option(
    '--api-key', '-a',
    help='your API key for the OpenWeatherMap API',
)
def main(location, api_key):
    """
    A little weather tool that shows you the current weather in a LOCATION of
    your choice. Provide the city name and optionally a two-digit country code.
    Here are two examples:
    1. London,UK
    2. Canmore
    You need a valid API key from OpenWeatherMap for the tool to work. You can
    sign up for a free account at https://openweathermap.org/appid.
    """
    weather = current_weather(location, api_key)
    print(f"The weather in {location} right now: {weather}.")


if __name__ == "__main__":
    main()

Перевод статьи «Writing Python Command-Line Tools With Click»

Содержание

Введение
Hello World! — первый скрипт на Python
Как запускать скрипты
Отступы (indentation)
Арифметика
if __name__ == ‘__main__’
!#: Shebang
Scopes: области видимости
Полезные ссылки
Похожие статьи

Введение

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

Синтаксис ядра Python минималистичен. В то же время стандартная библиотека
включает большой объём полезных функций.

Python поддерживает структурное, объектно-ориентированное, функциональное,
императивное и аспектно-ориентированное программирование.

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

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

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

Он распространяется под свободной лицензией Python Software Foundation License,
позволяющей использовать его без ограничений в любых приложениях, включая проприетарные.

Есть реализация интерпретатора для JVM с возможностью компиляции, CLR, LLVM,
другие независимые реализации. Проект PyPy использует JIT-компиляцию, которая
значительно увеличивает скорость выполнения Python-программ.

Python — активно развивающийся язык программирования, новые версии с
добавлением/изменением языковых свойств выходят примерно раз в два
с половиной года.

Язык не подвергался официальной стандартизации, роль
стандарта де-факто выполняет CPython, разрабатываемый под контролем автора языка.

В настоящий момент (апрель 2021)
Python занимает третье место в рейтинге TIOBE с показателем 11,03%.

Аналитики отмечают, что это самый высокий балл Python за все время его присутствия в
рейтинге.

Посмотреть текущий рейтинг можно

здесь

Hello World!

Инструкция по запуску первой программы в Python

Убедитесь, что Python установлен и команда

python -V

Показывает версию Python, например

Python 3.9.1

Если вы работаете в
Linux,
UNIX
или
Bash в Windows
перейдите в свою домашнюю директорию

В Linux

cd ~

В Windows

cd /mnt/c/Users/username

Создайте директорию python

mkdir python

Перейдите в неё, создайте файл hello_world.py
и откройте его любым тестовым редактором

cd python
touch hello_world.py
vi hello_world.py

Вставьте туда следующий код

print("Hello World!")

Выполните

python hello_world.py

В терминале должно появиться сообщение

Hello World!

Больше деталей о запуске скриптов вы можете найти в следующем параграфе —

«Запуск Python скрипта»

и затем в

if __name__ == «__main__»:

Запуск скрипта

Чтобы запустить .py скрипт введите

python имя_файла.py

Результат такого запуска зависит от того, что указано после

if __name__ == «__main__»:

если это условие вообще есть

print(«Hello!»)

python sample.py

Hello!

Теперь то же самое но в функции

def say_hello():
print(«Hello!»)

python sample.py

Ничего не произошло потому что функцию никто не вызвал

Можно добавить вызов функции следующим образом

def say_hello():
print(«Hello!»)

say_hello()

python sample.py

Hello!

В этом случае функция будет вызываться всегда — как при запуске скрипта из терминала так и при импорте в другой модуль
настроить это поведение можно с помощью переменной __name__ а точнее — с помощью условия

if __name__ == «__main__»:

Отступы (indentation)

Python не является языком поддерживающим свободный формат. Блоки кода не
разделяются с помощью { }

Вместо этого блоки разделяются отступами по так называемому правилу оффсайда (Off-side rule)

Демонстрация

Рассмотрим файл for_loop.py

for i in range(1,4):print(i)

python for_loop.py

1
2
3

Всё работает прекрасно. Обратите внимание, что выведены были только i от 1 до 3. 4 python не вывел.

Если написать код не в одну строку, а следующим образом

for i in range(1,4):
print(i)

то работать код не будет. Получится ошибка

File «/home/andrei/python/for_loop.py», line 2
print(i)
^
IndentationError: expected an indented block

Поэтому нужно поставить перед print пробел

for i in range(1,3):

print(i)

python for_loop.py

1
2
3

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

PEP8

— документ, в котором собраны рекомендации по написанию Python кода говорит:

Use 4 spaces per indentation level

САМОЕ ВАЖНОЕ: Нельзя смешивать в одном файле отступы в виде табуляций и в виде
пробелов. Выберите один стиль и придерживайтесь его.

Про то как правильно переносить слишком длинные строки можете прочитать

здесь

Арифметика

/ — деление. Результат — число с плавающей точкой

>>> 5 / 2

2.5

// — целочисленное деление. Результат — округлённое до целого числа частное.

>>> 5 // 2

2

% — остаток от деления. Результат — остаток от //

>>> 5 % 2

1

Печать спецсимволов HTML

for i in range(100001,125000):
print "<tr><td>&#",i,";</td><td>&#",i,";</td></tr>"

Ссылки

Psyco
Shedskin
PyPy

Cython
Jython
IronPython

IDLE

Синтаксис

Set в фигурных скобках. Элемент добавляется с помощью .add()

if __name__ == ‘__main__’

Чтобы разобраться в смысле этой строки создадим два файла.

first_module.py

и

second_module.py

В первом напишем

print(f"Имя первого модуля: {__name__}")

# Если не любите f-string напишите:
print("Имя первого модуля: {}".format(__name__))

Запустим его

python3 first_module.py

Имя первого модуля: __main__

Во втором запишем

import first_module

Запустим его

python3 second_module.py

Имя первого модуля: __first_module__

Вывод: когда модуль запущен непосредственно, его __name__ это __main__

Когда модуль импортирован в другой модуль, его __name__ это __название_py_файла__

Теперь когда все ясно, можно добавить в наш код условие if __name__ == «__main__»

def say_hello():
print(«Hello!»)

def display_name():
print(f«Имя первого модуля: {__name__}»)

if __name__ == «__main__»:
say_hello()

Hello!

Или

def say_hello():
print(«Hello!»)

def display_name():
print(f«Имя первого модуля: {__name__}»)

if __name__ == «__main__»:
display_name()

Имя первого модуля: __main__

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

Пакеты Python в Linux

Узнать сколько всего python3 пакетов в репозитории

Ubuntu

apt-cache search python3 | wc -l

3472

Изучить их названия можно с помощью less

apt-cache search python3 | less

alembic — lightweight database migration tool for SQLAlchemy

brltty — Access software for a blind person using a braille display

debian-goodies — Small toolbox-style utilities for Debian systems

devscripts — scripts to make the life of a Debian Package maintainer easier

libcrack2-dev — pro-active password checker library — development files

Проверить, существует ли файл

hosts

#!/usr/bin/python3

import os.path

if os.path.exists("/etc/hosts"):
print("hosts file exists")
else:
print("no hosts file")

или

#!/usr/bin/python3

try:
f = open('/etc/hosts')
print("hosts file exists")
except FileNotFoundError:
print("no hosts file")

python3 check_hosts.py

hosts file exists

Shebang

Указывает на нужный интерпретатор. Примеры:

#!/usr/bin/env python

#!/home/andrei/.pyenv/shims/python

После написаний шебанга нужно сделать скрипт выполняемым файлом

chmod + x имя_скрипта.py

И теперь его можно запускать прямо из терминала

./имя_скрипта.py

Или

.имя_скрипта.py

Scopes

Local — внутри функции

Enclosing — внутри фукнции, которая вызвала функцию

Global — во всем модуле

Built-in — встроено в Python

LEGB

Ссылки на Local уничтожаются после выполнения функции

Рассмотрим функцию fetch_words()
из статьи про

docstring

url, story, story_words, line, line_words, word — это локальные переменные

def fetch_words(url):
«»»Fetch a list of words from a URL.

Args:
url: The URL of a UTF-8 text document.

Returns:
A list of strings containing the words from
the document
«»»
# PEP 257
# story = urlopen(«http://sixty-north.com/c/t.txt»)
story = urlopen(url)
story_words = []
for line in story:
line_words = line.decode(«utf8»).split()
for word in line_words:
story_words.append(word)
story.close()
return story_words

def print_items(story_words):
«»»Print items one per line.

Args:
An iterable series of printable items.
«»»
for word in story_words:
print(word)

def main(url):
words = fetch_words(url)
print_items(words)

if __name__ == «__main__»:
main(sys.argv[1])

Разберем поведение глобальных переменных

count = 0

def show_count():
print(count)

def set_count(c):
count = c

show_count() # 0
set_count(5)
show_count() # 0

0
0

Изменить поведение функции можно с помощью global

count = 0

def show_count():
print(count)

def set_count(c):
global count
count = c

show_count() # 0
set_count(5) # Now affects global variable
show_count() # 5

0
5

Полезные ссылки

Похожие статьи

Основы Python
Python
Установка Python
ООП в Python
Функции
docstring
#!: Shebang
Объекты
Сложности при работе с Python

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

Почему в эпоху программирования мы все еще делаем то, что можем автоматизировать. Подумайте о задачах, которые вы повторяете ежедневно или ежедневных проектах, требующих автоматизации, таких как чтение электронной почты, редактирование изображений, чтение PDF и т. д. В этой статье мы рассмотрим 10 скриптов автоматизации для ваших повседневных задач.
Автоматизация решает проблему один раз, а затем ставит ее на автопилот
— Майкл Хаятт
👉 Автоматизируем отправку электронной почты с помощью Python
Этот потрясающий скрипт автоматизации позволит вам читать и отправлять электронные письма, будь то Outlook, Gmail или любой другой почтовый сервер. Ниже пример кода, который разделен на две части.
Чтение электронной почты и отправка электронной почты использует модуль IMAP для чтения электронных писем, а другой использует модуль SMTP для отправки электронной почты, ниже приведен код:

# Automate Emails with Python
import imaplib
import email
import smtplib
from email.mime.text import MIMEText
from email.mime.multipart import MIMEMultipart
# Read Email
Email = imaplib.IMAP4_SSL('imap.gmail.com')
Email.login('your_username', 'your_password')
status, msgs = Email.select('INBOX')    
print("Status: ", status)
for i in range(1, int(msgs[0])):
    res, message = Email.fetch(str(i), '(RFC822)')
    for r in message:
        if isinstance(r, tuple):
            message = email.message_from_bytes(r[1])
            print (message["subject"])
---------------------------------------------------
# Send Email
Your_Email = "test@xyz.com" 
password = "your_password"
reciver = "Sender Mail" 
subject = "Medium Article"
text_msg = "Hi, Codedev010 here from Medium Article"
msg = MIMEMultipart()
msg["From"] = Your_Email
msg["To"] = reciver
msg["Subject"] = subject
msg.attach(MIMEText(text_msg, 'plain'))
server = smtplib.SMTP("smtp.gmail.com", 587)
server.starttls()
server.login(Your_Email, password)
MSG = msg.as_string()
server.sendmail(Your_Email, reciver, MSG)
server.quit()

172 / 5 000

Результаты перевода

star_border

👉 Редактор изображений на Python

Используйте этот скрипт автоматизации для программного редактирования изображений. Ниже я приводу общие функции для редактирования изображений, такие как размытие, поворот, объединение изображений и т. д.

# Редактор изображений
# pip install pillow
from PIL import Image
from PIL import ImageDraw
# Combine Image
img1 = Image.open('img101.jpg')
img2 = Image.open('img102.jpg')
combine = Image.blend(img1, img2, 0.5)
# Resize Image
resize = Image.open('img101.jpg')
resize = resize.resize((300, 300))
# Flip an Image 
flip_image = Image.open('img101.jpg')
flip_image = flip_image.transpose(Image.FLIP_LEFT_RIGHT)
# Blur an Image
blur_image = Image.open('img101.jpg')
blur_image = blur_image.filter(Image.BLUR)
# Add Drop Shadow
shadow_image = Image.open('img101.jpg')
shadow_image = shadow_image.filter(Image.EDGE_ENHANCE_MORE)
# Crop an Image
crop_image = Image.open('img101.jpg')
crop_image = crop_image.crop((50, 50, 300, 200))
#Add Brightness
bright_image = Image.open('img101.jpg')
bright_image = bright_image.point(lambda p: p + 50)
# Add Text to Image
text_image = Image.open('img101.jpg')
text_image = text_image.convert('RGB')
draw = ImageDraw.Draw(text_image)
draw.text((10, 10), "Hello World", (255, 255, 255))
# Rotate an Image
rotate_image = Image.open('img101.jpg')
rotate_image = rotate_image.rotate(90)
# Save Image
img1.save('img101.jpg')

👉 Редактор аудио на Python
Этот скрипт автоматизации будет редактировать аудио файлы. Вы можете извлекать звуки, объединять их, воспроизводить, разделять/вырезать фрагменты аудио и многое другое. Скрипт использует модуль Pydub, который является модулем управления звуком. Код приведен ниже:

# Редактор аудио на Python
# pip install pydub
from pydub import AudioSegment
from pydub.utils import mediainfo
from pydub.playback import play
# Extract Sound from Video
sound = AudioSegment.from_file("video.mp4", format="mp4")
sound.export("music.mp3", format="mp3")
# Get Media Info
info = mediainfo("musci.wav")
print(info)
# Play Sound
play("music.mp3")
# Combine Sounds
sound1 = AudioSegment.from_file("music.mp3")
sound2 = AudioSegment.from_file("music.mp3")
combined = sound1 + sound2
combined.export("music_combined.mp3", format="mp3")
# Split Audio
sound = AudioSegment.from_file("music.mp3", format="mp3")
sound_1 = sound[:10000]
sound_2 = sound[10000:]
sound_1.export("music_1.mp3", format="mp3")
sound_2.export("music_2.mp3", format="mp3")
# Increase or Reduce Volumn
sound = AudioSegment.from_file("music.mp3", format="mp3")
sound_volumn = sound + 10
sound_volumn.export("music_volumn.mp3", format="mp3")
# Adding Silence to Audio
sound = AudioSegment.from_file("music.mp3", format="mp3")
sound_silence = sound + AudioSegment.silent(duration=1000)
sound_silence.export("music_silence.mp3", format="mp3")

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

https://t.me/pro_python_code – бесплатное обучение Python c нуля

# Lock Your Files
#pip install cryptography
from cryptography.fernet import Fernet
def Lock_file(file_name, key):
    with open(file_name, 'rb') as file:
        data = file.read()
    f = Fernet(key)
    encrypted_data = f.encrypt(data)
    with open(file_name, 'wb') as file:
        file.write(encrypted_data)
    print("File Lock...")
def Unlock_file(file_name, key):
    with open(file_name, 'rb') as file:
        data = file.read()
    f = Fernet(key)
    decrypted_data = f.decrypt(data)
    with open(file_name, 'wb') as file:
        file.write(decrypted_data)
    print("File Unlock...")
key = input("Enter the key: ")
Lock_file('test.txt', key)
Unlock_file('test.txt', key)

👉 Мобильные приложения на Python
Вы можете разрабатывать мобильные приложения с помощью Python. Модуль Kivy используется для разработки кроссплатформенных приложений, таких как Android, IOS и Win. В приведенном ниже коде будут важные виджеты Kivy, которые мы будем использовать для разработки приложения для начинающих.
Примечание. После того, как ваше приложение будет прочитано, вы можете собрать его Apk со следующим модулем: pip install buildozer

# Develop Mobile Apps with Kivy
# pip install kivy
from kivy.app import App
from kivy.uix.label import Label
from kivy.uix.button import Button
from kivy.uix.boxlayout import BoxLayout
from kivy.uix.textinput import TextInput
from kivy.uix.gridlayout import GridLayout
from kivy.uix.scrollview import ScrollView
from kivy.uix.checkbox import CheckBox    
from kivy.uix.image import Image
from kivy.uix.popup import Popup
class MobileApp(App):
def build(self):
        # Layout of App
        layout = BoxLayout(orientation="vertical")
# Label 
        label = Label(text="Hello Kivy!")
# Button
        btn = Button(text="Click Me!")
# Button Action
        btn.bind(on_press=self.btn_pressed)
# Input Box
        input_box = TextInput(hint_text="Input Here",size_hint=(.3,.2))
# Check Box
        check_box = CheckBox(text="Check Me!")
        
        # ScrollView
        scroll_view = ScrollView()
        grid_layout = GridLayout(cols=2, size_hint_y=None)
                      grid_layout.bind(minimum_height=grid_layout.setter('height'))
# Add Image to App
        image = Image(source="medium.png")
# Popup
        popup = Popup(title="Popup", size_hint=(.5,.5))
    
        # Add to layout
        layout.add_widget(label)
        layout.add_widget(btn)
        layout.add_widget(input_box)
        layout.add_widget(scroll_view)
        layout.add_widget(check_box)
        layout.add_widget(image)
        layout.add_widget(popup)
return layout
    def btn_pressed(self, instance):
        print("Button Pressed!")
# Run the App
app = MobileApp()
app.run()

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

import pyautogui
import numpy as np
import cv2
import keyboard
# pip install opencv-python
# pip install pyautogui
# pip install keyboard
# pip install numpy
def Screen_Recording():
    while True:
        # Press R to Start Recording
        if keyboard.is_pressed('r'):
            print("Recording Has been Started...")
            # resolution
            capture_area = (1920, 1080) 
            
            codec = cv2.VideoWriter_fourcc(*'mp4v')
            filename = "Your_Recording.mp4"
# Frame per Second
            fps = 60.0
            output_video = cv2.VideoWriter(filename, codec, fps, capture_area)
            while True:
                image = pyautogui.screenshot()
                Image_frame = np.array(image)
                Image_frame = cv2.cvtColor(Image_frame, cv2.COLOR_BGR2RGB)
                output_video.write(Image_frame)
                cv2.waitKey(1)
                # Press Q button to Stop recording
                if keyboard.is_pressed('q'):
                    print("Recording Has been Stopped...")
                    break
output_video.release()
            cv2.destroyAllWindows()
Screen_Recording()

👉 Проверка грамматики на Python
Проверка грамматики всегда сложна но этот скрипт автоматизации поможет вам. Этот удивительный скрипт использует модуль Gingerit, который подключен к API средства проверки Ginger Grammer, и второй модуль Streamlit для создания веб-приложений с меньшим количеством кода. Это удобный скрипт, когда у вас есть много текста или данных, которые нужно проверить программно.

# Proofreading with Pyton
# pip install gingerit
# pip install streamlit
from gingerit.gingerit import GingerIt
import streamlit as webapp
app = GingerIt()
webapp.title('Proofreading in Python')
Text = webapp.text_area("Enter Your Text or Sentence:", value='', height=None, max_chars=None, key=None)
if webapp.button('Correct Sentence'):
    if Text == '':
        webapp.write('Please enter text for proofreading') 
    else: 
        correction = app.parse(Text)
        webapp.markdown('Corrected Text => ' + str(correction["result"]))

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

# Extract Tables from Camelot
# pip install camelot-py
import camelot
table = camelot.read_pdf('test.pdf', pages='1-2')
# get total number of tables
print("Total tables: ", table.n) # 2
# print table by num
print(table[0].df)
print(table[1].df)
# Export Table to CSV
table[0].to_csv('table1.csv')
table[1].to_csv('table2.csv')
# Export Table to Excel
table[0].to_excel('table1.xlsx')
# Export Table to HTML
table[0].to_html('table1.html')
# Extract and Export Table At Once
table.export('tables.csv', f='csv', compress=True)
# Parse Table Report
table[0].parse(['Date', 'Description', 'Amount'])

👉 Автоматизируем работу MS Excel, Word и PowerPoint
Думали ли вы, что с помощью Python можно также автоматизировать программное обеспечение MS Office? Тогда этот скрипт позволит вам это сделать. Скрипт разделен на три части, и каждая часть имеет модуль для чтения и записи данных в программном обеспечении MS.

# Автоматизируем работу MS Excel, Word и PowerPoint
# pip install xlrd
import xlrd
wb = xlrd.open_workbook('test.xlsx')
worksheet = wb.sheet_by_index(0)
# Read by row and col number
print(worksheet.cell_value(0, 0))
# read whole row
print(worksheet.row_values(0))
# read whole col
print(worksheet.col_values(1))
# Write to excel by row and col number
worksheet.write(0, 0, 'Hello')
wb.save('test.xlsx')
-------------------------------------------------
# Automate MS WORD
# pip install python-docx
import docx
 
doc = docx.Document("zen_of_python.docx")
 
# read paragraph by paragraph
text = [p.text for p in doc.paragraphs]
print(text)
# read table by table
for table in doc.tables:
    for row in table.rows:
        for cell in row.cells:
            print(cell.text)
# Write in Doc
doc.add_paragraph("Hello World")
doc.save("test.docx")
-------------------------------------------------
# Automate PowerPoint
# pip install python-pptx
from pptx import Presentation
# Read Slides
PP = Presentation('file.pptx')
for slide in PP.slides:
    for shape in slide.shapes:
        for paragraph in shape.text_frame.paragraphs:
            for data in paragraph.runs:
                print(data.text)
# Write in PPT
PP = Presentation()
title_slide_layout = PP.slide_layouts[0]
slide = PP.slides.add_slide(title_slide_layout)
title = slide.shapes.title
title.text = "Medium Article"
PP.save('file.pptx')

👉 Преобразовываем Изображение в PDF с Python
Этот простой скрипт автоматизации поможет вам преобразовать ваши изображения в формат PDF.

# Images to Python
from PIL import Image
def Images_Pdf(filename, output):
    images = []
for file in filename:
        im = Image.open(file)
        im = im.convert('RGB')
        images.append(im)
    
    images[0].save(output, save_all=True, append_images=images[1:])
Images_Pdf(["test1.jpg", "test2.jpg", "test3.jpg"], "output.pdf")

👉Заключительные мысли
Что ж, я очень рад, что вы дошли до конца этой статьи, и я надеюсь, что вы найдете ее информативной и получили удовольствие от ее чтения. Если вам понравилась эта статья, не забудьте поделиться ❤️ ею со своими друзьями.

Больше полезных скриптов в нашем телеграмм канале по аналитике данных на Python

https://t.me/data_analysis_ml

Просмотры: 3 676

Понравилась статья? Поделить с друзьями:
  • Написать программу на c под windows
  • Написано подготовка windows не выключайте компьютер бесконечная загрузка
  • Написание скриптов на python для windows
  • Написание приложения для ios на windows
  • Написание bat файлов для windows 10