Как написать приложение для ios на python

В наши дни каждый разработчик может столкнуться с необходимостью работы над мобильным или веб-приложением на Python. В Python нет встроенных инструментов для мобильных устройств, тем не менее существуют пакеты, которые можно использовать для создания мобильных приложений. Это Kivy, PyQt и даже библиотека Toga от Beeware.

Содержание

  • Принципы работы фреймворка Kivy Python
  • Установка Kivy
  • Работа с виджетами в Kivy
  • Запуск программы «Hello, Kivy!»
  • Отображение виджета Image в Kivy Python
  • Разметка (Layout) в UI Kivy
  • Добавление событий в Kivy
  • Использование языка дизайна KV
  • Создание приложения Kivy Python
  • Создаем apk приложения для Android на Python
  • Создание приложений для iPhone (iOS) на Python
  • Создание exe приложений для Windows на Python используя Kivy
  • Создание приложений для macOS на Python используя Kivy

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

В руководстве будут разобраны следующие темы:

  • Работа с виджетами Kivy;
  • Планировка UI и лейауты;
  • Добавление событий;
  • Использование языка KV;
  • Создание приложения-калькулятора;
  • Упаковка приложения для iOS, Android, Windows и macOS.

Разбор данного руководства предполагает, что читатель знаком с объектно-ориентированным программированием. Для введения в курс дела можете просмотреть статью об Объектно-ориентированном программировании (ООП) в Python 3.

Приступим!

Принципы работы фреймворка Kivy Python

Kivy был создан в 2011 году. Данный кросс-платформенный фреймворк Python работает на Windows, Mac, Linux и Raspberry Pi. В дополнение к стандартному вводу через клавиатуру и мышь он поддерживает мультитач. Kivy даже поддерживает ускорение GPU своей графики, что во многом является следствием использования  OpenGL ES2. У проекта есть лицензия MIT, поэтому библиотеку можно использовать бесплатно и вкупе с коммерческим программным обеспечением.

Во время разработки приложения через Kivy создается интуитивно понятный интерфейс (Natural user Interface), или NUI. Его главная идея в том, чтобы пользователь мог легко и быстро приспособиться к программному обеспечению без чтения инструкций.

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

Установка Kivy

У Kivy есть множество зависимостей, поэтому лучше устанавливать его в виртуальную среду Python. Можно использовать встроенную библиотеку Python venv или же пакет virtualenv.

Виртуальная среда Python создается следующим образом:

$ python3 m venv my_kivy_project

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

Есть вопросы по Python?

На нашем форуме вы можете задать любой вопрос и получить ответ от всего нашего сообщества!

Telegram Чат & Канал

Вступите в наш дружный чат по Python и начните общение с единомышленниками! Станьте частью большого сообщества!

Паблик VK

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

Для использования виртуальной среды ее нужно активировать. На Mac или Linux это можно сделать, выполнив следующую команду, будучи внутри папки my_kivy_project:

Команда для Windows точно такая же, но активировать скрипт нужно в другом месте — через папку Scripts, а не bin.

После активации виртуальной среды Python можно запустить pip для установки Kivy. На Linux и Mac нужно выполнить следующую команду:

$ python m pip install kivy

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

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

Работа с виджетами в Kivy

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

Запуск программы «Hello, Kivy!»

Принцип работы Kivy можно уловить, взглянув на следующее приложение «Hello, World!»:

from kivy.app import App

from kivy.uix.label import Label

class MainApp(App):

    def build(self):

        label = Label(text=‘Hello from Kivy’,

                      size_hint=(.5, .5),

                      pos_hint={‘center_x’: .5, ‘center_y’: .5})

        return label

if __name__ == ‘__main__’:

    app = MainApp()

    app.run()

Каждому приложению Kivy требуется создать подкласс App и переопределить метод build().  Сюда вы помещаете код UI или вызываете другие функции, которые определяют код UI. В данном случае создается виджет Label и передается text, size_hint и pos_hint. Последние два аргумента не обязательны.

size_hint говорит Kivy о размерах что нужно использовать при создании виджета. Используются два числа:

  1. Первое число x указывает на размер ширины элемента управления.
  2. Второе число y указывает на размер высоты элемента управления.

Значение обоих чисел должно быть в промежутке между 0 и 1. Значение по обоих показателей по умолчанию равно 1. Также можно задействовать pos_hint, что используется для позиционирования виджета. В коде, размещенном выше, указывается, что виджет должен быть размещен в центре осей x и y.

Для запуска приложения нужно инициализировать класс MainApp и вызвать метод run(). После этих действий на экране появится следующее:

App Hello from Kivy

Kivy также выводит в stdout довольно много текста:

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

[INFO   ] [Logger      ] Record log in /home/mdriscoll/.kivy/logs/kivy_190607_2.txt

[INFO   ] [Kivy        ] v1.11.0

[INFO   ] [Kivy        ] Installed at «/home/mdriscoll/code/test/lib/python3.6/site-packages/kivy/__init__.py»

[INFO   ] [Python      ] v3.6.7 (default, Oct 22 2018, 11:32:17)

[GCC 8.2.0]

[INFO   ] [Python      ] Interpreter at «/home/mdriscoll/code/test/bin/python»

[INFO   ] [Factory     ] 184 symbols loaded

[INFO   ] [Image       ] Providers: img_tex, img_dds, img_sdl2, img_gif (img_pil, img_ffpyplayer ignored)

[INFO   ] [Text        ] Provider: sdl2([‘text_pango’] ignored)

[INFO   ] [Window      ] Provider: sdl2([‘window_egl_rpi’] ignored)

[INFO   ] [GL          ] Using the «OpenGL» graphics system

[INFO   ] [GL          ] Backend used <sdl2>

[INFO   ] [GL          ] OpenGL version <b‘4.6.0 NVIDIA 390.116’>

[INFO   ] [GL          ] OpenGL vendor <b‘NVIDIA Corporation’>

[INFO   ] [GL          ] OpenGL renderer <b‘NVS 310/PCIe/SSE2’>

[INFO   ] [GL          ] OpenGL parsed version: 4, 6

[INFO   ] [GL          ] Shading version <b‘4.60 NVIDIA’>

[INFO   ] [GL          ] Texture max size <16384>

[INFO   ] [GL          ] Texture max units <32>

[INFO   ] [Window      ] auto add sdl2 input provider

[INFO   ] [Window      ] virtual keyboard not allowed, single mode, not docked

[INFO   ] [Base        ] Start application main loop

[INFO   ] [GL          ] NPOT texture support is available

Это может быть полезно для отладки приложения.

Далее добавим виджет Image и посмотрим, чем он отличается от Label.

Отображение виджета Image в Kivy Python

В Kivy есть несколько видов виджетов, связанных с изображениями. Для загрузки картинок с жесткого диска можно задействовать Image, а при использовании адреса URL подойдет AsyncImage. К следующем примере берется стандартный класс Image:

from kivy.app import App

from kivy.uix.image import Image

class MainApp(App):

    def build(self):

        img = Image(source=‘/path/to/real_python.png’,

                    size_hint=(1, .5),

                    pos_hint={‘center_x’:.5, ‘center_y’:.5})

        return img

if __name__ == ‘__main__’:

    app = MainApp()

    app.run()

В данном коде импортируется Image из подпакета kivy.uix.image. Класс Image принимает много разных параметров, однако единственным для нас нужным является source, что указывает Kivy, какое изображение должно быть загружено. Здесь передается полный путь к выбранному изображению. Оставшаяся часть кода такая же, как и в прошлом примере.

После запуска кода должно выводиться нечто подобное:

Load Image Kivy

Текст из предыдущего примера был заменен картинкой.

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

Разметка (Layout) в UI Kivy

У каждого фреймворка есть свой собственный метод для размещения виджетов. К примеру, в wxPython используются классификаторы, а в Tkinter будет задействован лейаут, или менеджер геометрии. В Kivy за это отвечают Лейауты (Layouts). Доступно несколько различных типов Лейаутов. Чаще всего используются следующие виды:

  • BoxLayout;
  • FloatLayout;
  • GridLayout.

Найти полный список доступных Лейаутов можно в документации Kivy. Рабочий исходный код можно найти в kivy.uix.

Рассмотрим BoxLayout на примере следующего кода:

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

import kivy

import random

from kivy.app import App

from kivy.uix.button import Button

from kivy.uix.boxlayout import BoxLayout

red = [1,0,0,1]

green = [0,1,0,1]

blue =  [0,0,1,1]

purple = [1,0,1,1]

class HBoxLayoutExample(App):

    def build(self):

        layout = BoxLayout(padding=10)

        colors = [red, green, blue, purple]

        for i in range(5):

            btn = Button(text=«Button #%s» % (i+1),

                         background_color=random.choice(colors)

                         )

            layout.add_widget(btn)

        return layout

if __name__ == «__main__»:

    app = HBoxLayoutExample()

    app.run()

Здесь из kivy.uix.boxlayout импортируется модуль BoxLayout и затем устанавливается. После этого создается список цветов, которые представляют собой цвета RGB (Red-Blue-Green).

В конечном итоге формируется цикл для range из 5, результатом чего является кнопка btn для каждой итерации. Сделаем вещи немного интереснее и поставим в качестве фона кнопки background_color случайный цвет. Теперь можно добавить кнопку в лейаут при помощи layout.add_widget(btn).

После запуска кода выведется нечто подобное:

Kivy Hbox Layout

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

Во время создания лейаута следует учитывать следующие аргументы:

  • padding: Отступ padding между лейаутом и его дочерними элементами уточняется в пикселях. Для этого можно выбрать один из трех способов:
    1. Список из четырех аргументов: [padding_left, padding_top, padding_right, padding_bottom]
    2. Список из двух аргументов: [padding_horizontal, padding_vertical]
    3. Один аргумент: padding=10
  • spacing: При помощи данного аргумента добавляется расстояние между дочерними виджетами.
  • orientation: Позволяет изменить значение orientation для BoxLayout по умолчанию — с горизонтального на вертикальное.

Добавление событий в Kivy

Как и многие другие инструментарии GUI, по большей части Kivy полагается на события. Фреймворк отзывается на нажатие клавиш, кнопки мышки или прикосновение к сенсорному экрану. В Kivy задействован концепт Часов (Clock), что дает возможность создать своего рода график для вызова определенных функций в будущем.

В Kivy также используется концепт Свойств (Properties), что работает с EventDispatcher. Свойства помогают осуществить проверку достоверности. Они также запускают события, когда виджет меняет размер или позицию.

Добавим событие для кнопки из предыдущего кода:

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

from kivy.app import App

from kivy.uix.button import Button

class MainApp(App):

    def build(self):

        button = Button(text=‘Hello from Kivy’,

                        size_hint=(.5, .5),

                        pos_hint={‘center_x’: .5, ‘center_y’: .5})

        button.bind(on_press=self.on_press_button)

        return button

    def on_press_button(self, instance):

        print(‘Вы нажали на кнопку!’)

if __name__ == ‘__main__’:

    app = MainApp()

    app.run()

В данном коде вызывается button.bind(), а событие on_press ссылается на MainApp.on_press_button().

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

Использование языка дизайна KV

Kivy предоставляет язык дизайна KV, что можно использовать в приложениях Kivy. Язык KV позволяет отделить дизайн интерфейса от логики приложения. Он придерживается принципа разделения ответственности и является частью архитектурного паттерна Модель-Представление-Контроллер (Model-View-Controller).  Предыдущий пример можно обновить, используя язык KV:

from kivy.app import App

from kivy.uix.button import Button

class ButtonApp(App):

    def build(self):

        return Button()

    def on_press_button(self):

        print(‘Вы нажали на кнопку!’)

if __name__ == ‘__main__’:

    app = ButtonApp()

    app.run()

С первого взгляда данный код может показаться несколько странным, так как кнопка Button создается без указания атрибутов или привязывания к ним событий. Здесь Kivy автоматически ищет файл с таким же названием, что и у класса, только строчными буквами и без части App в названии класса.

В данном случае названием класса является ButtonApp, поэтому Kivy будет искать файл button.kv. Если такой файл существует, и он также форматирован должным образом, тогда Kivy использует его при загрузке UI. Попробуйте создать такой файл и добавить следующий код:

<Button>:

    text: ‘Press me’

    size_hint: (.5, .5)

    pos_hint: {‘center_x’: .5, ‘center_y’: .5}

    on_press: app.on_press_button()

Действия каждой строки:

  • Строка 1 соответствует вызову Button в коде Python. Kivy должен осмотреть инициализированный объект для определения кнопки;
  • Строка 2 устанавливает text кнопки;
  • Строка 3 устанавливает ширину и высоту при помощи size_hint;
  • Строка 4 устанавливает позицию кнопки через pos_hint;
  • Строка 5 устанавливает обработчик событий on_press. Для указания Kivy места обработчика событий используется app.on_press_button(). Здесь Kivy будет искать метод .on_press_button() в классе Application.

Вы можете установить все ваши виджеты и лейауты внутри одного или нескольких файлов языка KV. Язык KV также поддерживает импорт модулей Python в KV, создавая динамичные классы, и это далеко не предел. Ознакомиться с полным перечнем его возможностей можно в гиде Kivy по языку KV.

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

Создание приложения Kivy Python

Создание чего-то полезное несомненно является отличным способом выучить новый навык. Учитывая данное утверждение, давайте используем Kivy при создании калькулятора, который будет поддерживать следующие операции:

  • Сложение;
  • Вычитание;
  • Умножение;
  • Деление.

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

Kivy Calculator

Теперь, когда у нас есть в наличии целевой UI, может составить код:

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

from kivy.app import App

from kivy.uix.boxlayout import BoxLayout

from kivy.uix.button import Button

from kivy.uix.textinput import TextInput

class MainApp(App):

    def build(self):

        self.operators = [«/», «*», «+», «-«]

        self.last_was_operator = None

        self.last_button = None

        main_layout = BoxLayout(orientation=«vertical»)

        self.solution = TextInput(

            multiline=False, readonly=True, halign=«right», font_size=55

        )

        main_layout.add_widget(self.solution)

        buttons = [

            [«7», «8», «9», «/»],

            [«4», «5», «6», «*»],

            [«1», «2», «3», «-«],

            [«.», «0», «C», «+»],

        ]

        for row in buttons:

            h_layout = BoxLayout()

            for label in row:

                button = Button(

                    text=label,

                    pos_hint={«center_x»: 0.5, «center_y»: 0.5},

                )

                button.bind(on_press=self.on_button_press)

                h_layout.add_widget(button)

            main_layout.add_widget(h_layout)

        equals_button = Button(

            text=«=», pos_hint={«center_x»: 0.5, «center_y»: 0.5}

        )

        equals_button.bind(on_press=self.on_solution)

        main_layout.add_widget(equals_button)

        return main_layout

Калькулятор работает следующим образом:

  • В строках с 8 по 10 создается список operators и несколько полезных значений, last_was_operator и last_button, которые будут использованы чуть позже.
  • В строках с 11 по 15 создается лейаут верхнего уровня main_layout, к нему также добавляется виджет только для чтения TextInput.
  • В строках с 16 по 21 создается вложенный список из списков, где есть большая часть кнопок для калькулятора.
  • В строке 22 начинается цикл for для кнопок. Для каждого вложенного списка делается следующее:
    1. В строке 23 создается BoxLayout с горизонтальной ориентацией.
    2. В строке 24 начинается еще один цикл for для элементов вложенного списка.
    3. В строках с 25 по 39 создаются кнопки для ряда и связываются обработчиком событий, после чего кнопки добавляются к горизонтальному BoxLayout из строки 23.
    4. В строке 31 этот лейаут добавляется к main_layout.
  • В строках с 33 по 37 создается кнопка равно (=) и привязывается к обработчику событий, после чего она добавляется к main_layout.

Далее создается обработчик событий .on_button_press(). Код будет выглядеть следующим образом:

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

def on_button_press(self, instance):

    current = self.solution.text

    button_text = instance.text

    if button_text == «C»:

        # Очистка виджета с решением

        self.solution.text = «»

    else:

        if current and (

            self.last_was_operator and button_text in self.operators):

            # Не добавляйте два оператора подряд, рядом друг с другом

            return

        elif current == «» and button_text in self.operators:

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

            return

        else:

            new_text = current + button_text

            self.solution.text = new_text

    self.last_button = button_text

    self.last_was_operator = self.last_button in self.operators

Почти все виджеты приложения вызывают .on_button_press(). Это работает следующим образом:

  • Строка 41 принимает аргумент instance, в результате чего можно узнать, какой виджет вызвал функцию.
  • Строки между 42 и 43 извлекают и хранят значения solution и text кнопки.
  • Строки c 45 по 47 проверяют, на какую кнопку нажали. Если пользователь нажимает с, тогда очищается solution. В противном случае используется утверждение else.
  • Строка 49 проверяет, было ли у решения предыдущее значение.
  • Строки с 50 по 52 проверяют, была ли последняя нажатая кнопка оператором. Если да, тогда solution обновляться не будет. Это необходимо для предотвращения создания двух операций в одном ряду. К примеру, 1 * / будет недействительным утверждением.
  • Строки с 53 по 55 проверяют, является ли первый символ оператором. Если да, тогда solution обновляться не будет, так как первое значение не может быть значением оператора.
  • Строки с 56 по 58 переходят к условию else. Если никакое из предыдущих значений не найдено, тогда обновляется solution.
  • Строка 59 устанавливает last_button к метке последней нажатой кнопки.
  • Строка 60 устанавливает last_was_operator к значению True или False в зависимости от того, был символ оператором или нет.

Последней частью кода будет .on_solution():

def on_solution(self, instance):

    text = self.solution.text

    if text:

        solution = str(eval(self.solution.text))

        self.solution.text = solution

Здесь берется текущий текст из solution и используется встроенный в Python eval() для исполнения. Если пользователь создал формулу вроде 1+2, тогда eval() запустит код и вернет результат. В конце результат устанавливается как новое значение виджета solution.

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

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

KV Calculator

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

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

from kivy.app import App

from kivy.uix.boxlayout import BoxLayout

from kivy.uix.button import Button

from kivy.uix.textinput import TextInput

class MainApp(App):

    def build(self):

        self.operators = [«/», «*», «+», «-«]

        self.last_was_operator = None

        self.last_button = None

        main_layout = BoxLayout(orientation=«vertical»)

        self.solution = TextInput(

            multiline=False, readonly=True, halign=«right», font_size=55

        )

        main_layout.add_widget(self.solution)

        buttons = [

            [«7», «8», «9», «/»],

            [«4», «5», «6», «*»],

            [«1», «2», «3», «-«],

            [«.», «0», «C», «+»],

        ]

        for row in buttons:

            h_layout = BoxLayout()

            for label in row:

                button = Button(

                    text=label,

                    pos_hint={«center_x»: 0.5, «center_y»: 0.5},

                )

                button.bind(on_press=self.on_button_press)

                h_layout.add_widget(button)

            main_layout.add_widget(h_layout)

        equals_button = Button(

            text=«=», pos_hint={«center_x»: 0.5, «center_y»: 0.5}

        )

        equals_button.bind(on_press=self.on_solution)

        main_layout.add_widget(equals_button)

        return main_layout

    def on_button_press(self, instance):

        current = self.solution.text

        button_text = instance.text

        if button_text == «C»:

            # Очистка виджета с решением

            self.solution.text = «»

        else:

            if current and (

                self.last_was_operator and button_text in self.operators):

                # Не добавляйте два оператора подряд, рядом друг с другом

                return

            elif current == «» and button_text in self.operators:

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

                return

            else:

                new_text = current + button_text

                self.solution.text = new_text

        self.last_button = button_text

        self.last_was_operator = self.last_button in self.operators

    def on_solution(self, instance):

        text = self.solution.text

        if text:

            solution = str(eval(self.solution.text))

            self.solution.text = solution

if __name__ == «__main__»:

    app = MainApp()

    app.run()

Пришло время разместить приложение в Google Play или в AppStore!

По завершении составления кода вы можете поделиться своим приложением с другими. Хорошим способом сделать это может стать превращение вашего кода в приложения для смартфона на Android. Для этого вначале нужно установить пакет buildozer через pip:

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

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

[app]

# (str) Название вашего приложения

title = KvCalc

# (str) Название упаковки

package.name = kvcalc

# (str) Домен упаковки (нужен для упаковки android/ios)

package.domain = org.kvcalc

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

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

Теперь можно запустить следующую команду:

$ buildozer v android debug

Этап сборки займет время! На моем компьютере на это ушло около 15-20 минут. Здесь все зависит от вашего железа, так что времени может потребоваться еще больше. Расслабьтесь, налейте чашечку кофе или прогуляйтесь. Buildozer скачает те элементы Android SDK, которые нужны для процесса сборки. Если все идет по плану, тогда в папке bin появится файл под названием, напоминающим что-то вроде kvcalc-0.1-debug.apk.

Далее требуется связать телефон Android с компьютером и перенести туда файл apk. Затем откройте менеджер файлов телефона и кликните на файл apk. Android должен спросить, хотите ли вы установить приложение. Есть вероятность появления предупреждения, ведь приложение было скачано не из Google Play. Тем не менее, вы по-прежнему сможете установить его.

Вот как выглядит калькулятор, запущенный на Samsung S9:

KV Calc Android

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

При необходимости добиться более детального управления упаковку можно осуществить через python-for-android. Здесь это обсуждаться не будет, но если интересно, ознакомьтесь, как еще можно быстро начать проект.

Создание приложений для iPhone (iOS) на Python

Инструкция для сборки приложения для iOS будет немного сложнее, нежели для Android. Для получения последней информации всегда проверяйте обновления официальной документации Kivy.

Вам нужен будет компьютер с операционной системой OS X: MacBook или iMac. На Linux или Windows вы не сможете создать приложения для Apple.

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

$ brew install autoconf automake libtool pkgconfig

$ brew link libtool

$ sudo easy_install pip

$ sudo pip install Cython==0.29.10

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

$ git clone git://github.com/kivy/kivyios

$ cd kivyios

$ ./toolchain.py build python3 kivy

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

Если вы получаете ошибки SSL, тогда скорее всего у вас не установлен OpenSSL от Python. Следующая команда должна это исправить:

$ cd /Applications/Python 3.7/

$ ./Install Certificates.command

Теперь вернитесь назад и запустите команду toolchain опять.

После успешного выполнения всех указанных выше команд можете создать проект Xcode при помощи использования скрипта toolchain. Перед созданием проекта Xcode переименуйте ваше главное приложение в main.py, это важно. Выполните следующую команду.

./toolchain.py create <title> <app_directory>

Здесь должна быть папка под названием title, внутри которой будет проект Xcode. Теперь можно открыть проект Xcode и работать над ним отсюда. Обратите внимание, что если вы хотите разместить свое приложение на AppStore, вам понадобится создать аккаунт разработчика на developer.apple.com и заплатить годовой взнос.

Создание exe приложений для Windows на Python используя Kivy

Упаковать приложение Kivy для Windows можно при помощи PyInstaller. Если ранее вы никогда не работали с ним, тогда изучите тему использования PyInstaller для упаковки кода Python в исполняемый файл.

Для установки PyInstaller можно использовать pip:

$ pip install pyinstaller

Следующая команда упакует ваше приложение:

Команда создаст исполняемый файл Windows, а вместе с ним еще несколько других файлов. Аргумент -w говорит PyInstaller, что приложение открывается в оконном режиме и не является приложение для командной строки. Если вы хотите, чтобы PyInstaller создал только один исполняемый файл, тогда можете передать в дополнение к -w аргумент --onefile.

Создание приложений для macOS на Python используя Kivy

Как и в случае с Windows, для создания исполняемого файла Mac можно также использовать PyInstaller. Единственным условием является запуск следующей команды на Mac:

$ pyinstaller main.py w onefile

Результатом станет один исполняемый файл в папке dist. Название исполняемого файла будет таким же, как и название файла Python, что был передан PyInstaller.

Если вы хотите уменьшить размер исполняемого файла или использовать в приложении GStreamer, тогда для получения дополнительной информации изучите тему упаковки для macOS.

Заключение

Kivy является действительно интересным фреймворком GUI, что можно использовать для создания пользовательских интерфейсов и мобильных приложений для Android и iOS. Внешне приложения Kivy будут отличаться от нативных приложений выбранной платформы. В том случае, если вы хотите выделяться на фоне конкурентов, это может быть выгодным преимуществом.

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

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

Рекомендации

Для дальнейшего изучения Kivy ознакомьтесь со следующими ресурсами:

  • Гид программирования на Kivy 
  • Документация по упаковке приложений Kivy
  • Сборка приложений GUI через Python

Чтобы посмотреть, как создать приложение с графическим интерфейсом при использовании другого GUI фреймфорка Python, можете ознакомиться со статьями о wxPython.

Являюсь администратором нескольких порталов по обучению языков программирования Python, Golang и Kotlin. В составе небольшой команды единомышленников, мы занимаемся популяризацией языков программирования на русскоязычную аудиторию. Большая часть статей была адаптирована нами на русский язык и распространяется бесплатно.

E-mail: vasile.buldumac@ati.utm.md

Образование
Universitatea Tehnică a Moldovei (utm.md)

  • 2014 — 2018 Технический Университет Молдовы, ИТ-Инженер. Тема дипломной работы «Автоматизация покупки и продажи криптовалюты используя технический анализ»
  • 2018 — 2020 Технический Университет Молдовы, Магистр, Магистерская диссертация «Идентификация человека в киберпространстве по фотографии лица»

Watch Now This tutorial has a related video course created by the Real Python team. Watch it together with the written tutorial to deepen your understanding: Build Cross-Platform GUI Apps With Kivy

These days, developers are highly likely to be working on a mobile or web application. Python doesn’t have built-in mobile development capabilities, but there are packages you can use to create mobile applications, like Kivy, PyQt, or even Beeware’s Toga library.

These libraries are all major players in the Python mobile space. However, there are some benefits you’ll see if you choose to create mobile applications with Kivy. Not only will your application look the same on all platforms, but you also won’t need to compile your code after every change. What’s more, you’ll be able to use Python’s clear syntax to build your applications.

In this tutorial, you’ll learn how to:

  • Work with Kivy widgets
  • Lay out the UI
  • Add events
  • Use the KV language
  • Create a calculator application
  • Package your application for iOS, Android, Windows, and macOS

This tutorial assumes you’re familiar with object-oriented programming. If you’re not, then check out Object-Oriented Programming (OOP) in Python 3.

Let’s get started!

Understanding the Kivy Framework

Kivy was first released in early 2011. This cross-platform Python framework can be deployed to Windows, Mac, Linux, and Raspberry Pi. It supports multitouch events in addition to regular keyboard and mouse inputs. Kivy even supports GPU acceleration of its graphics, since they’re built using OpenGL ES2. The project uses the MIT license, so you can use this library for free and commercial software.

When you create an application with Kivy, you’re creating a Natural User Interface or NUI. The idea behind a Natural User Interface is that the user can easily learn how to use your software with little to no instruction.

Kivy does not attempt to use native controls or widgets. All of its widgets are custom-drawn. This means that Kivy applications will look the same across all platforms. However, it also means that your app’s look and feel will differ from your user’s native applications. This could be a benefit or a drawback, depending on your audience.

Installing Kivy

Kivy has many dependencies, so it’s recommended that you install it into a Python virtual environment. You can use either Python’s built-in venv library or the virtualenv package. If you’ve never used a Python virtual environment before, then check out Python Virtual Environments: A Primer.

Here’s how you can create a Python virtual environment:

$ python3 -m venv my_kivy_project

This will copy your Python 3 executable into a folder called my_kivy_project and add a few other subfolders to that directory.

To use your virtual environment, you need to activate it. On Mac and Linux, you can do that by executing the following while inside the my_kivy_project folder:

The command for Windows is similar, but the location of the activate script is inside of the Scripts folder instead of bin.

Now that you have an activated Python virtual environment, you can run pip to install Kivy. On Linux and Mac, you’ll run the following command:

$ python -m pip install kivy

On Windows, installation is a bit more complex. Check out the official documentation for how to install Kivy on Windows. (Mac users can also download a dmg file and install Kivy that way.)

If you run into any issues installing Kivy on your platform, then see the Kivy download page for additional instructions.

Working With Kivy Widgets

A widget is an onscreen control that the user will interact with. All graphical user interface toolkits come with a set of widgets. Some common widgets that you may have used include buttons, combo boxes, and tabs. Kivy has many widgets built into its framework.

Running a “Hello, Kivy!” Program

To see how Kivy works, take a look at the following “Hello, World!” application:

from kivy.app import App
from kivy.uix.label import Label

class MainApp(App):
    def build(self):
        label = Label(text='Hello from Kivy',
                      size_hint=(.5, .5),
                      pos_hint={'center_x': .5, 'center_y': .5})

        return label

if __name__ == '__main__':
    app = MainApp()
    app.run()

Every Kivy application needs to subclass App and override build(). This is where you’ll put your UI code or make calls to other functions that define your UI code. In this case, you create a Label widget and pass in its text, size_hint, and pos_hint. These last two arguments are not required.

size_hint tells Kivy the proportions to use when creating the widget. It takes two numbers:

  1. The first number is the x size hint and refers to the width of the control.
  2. The second number is the y size hint and refers to the height of the control.

Both of these numbers can be anywhere between 0 and 1. The default value for both hints is 1. You can also use pos_hint to position the widget. In the code block above, you tell Kivy to center the widget on the x and y axes.

To make the application run, you instantiate your MainApp class and then call run(). When you do so, you should see the following on your screen:

Hello World in Kivy

Kivy also outputs a lot of text to stdout:

[INFO   ] [Logger      ] Record log in /home/mdriscoll/.kivy/logs/kivy_19-06-07_2.txt
[INFO   ] [Kivy        ] v1.11.0
[INFO   ] [Kivy        ] Installed at "/home/mdriscoll/code/test/lib/python3.6/site-packages/kivy/__init__.py"
[INFO   ] [Python      ] v3.6.7 (default, Oct 22 2018, 11:32:17)
[GCC 8.2.0]
[INFO   ] [Python      ] Interpreter at "/home/mdriscoll/code/test/bin/python"
[INFO   ] [Factory     ] 184 symbols loaded
[INFO   ] [Image       ] Providers: img_tex, img_dds, img_sdl2, img_gif (img_pil, img_ffpyplayer ignored)
[INFO   ] [Text        ] Provider: sdl2(['text_pango'] ignored)
[INFO   ] [Window      ] Provider: sdl2(['window_egl_rpi'] ignored)
[INFO   ] [GL          ] Using the "OpenGL" graphics system
[INFO   ] [GL          ] Backend used <sdl2>
[INFO   ] [GL          ] OpenGL version <b'4.6.0 NVIDIA 390.116'>
[INFO   ] [GL          ] OpenGL vendor <b'NVIDIA Corporation'>
[INFO   ] [GL          ] OpenGL renderer <b'NVS 310/PCIe/SSE2'>
[INFO   ] [GL          ] OpenGL parsed version: 4, 6
[INFO   ] [GL          ] Shading version <b'4.60 NVIDIA'>
[INFO   ] [GL          ] Texture max size <16384>
[INFO   ] [GL          ] Texture max units <32>
[INFO   ] [Window      ] auto add sdl2 input provider
[INFO   ] [Window      ] virtual keyboard not allowed, single mode, not docked
[INFO   ] [Base        ] Start application main loop
[INFO   ] [GL          ] NPOT texture support is available

This is useful for debugging your application.

Next, you’ll try adding an Image widget and see how that differs from a Label.

Displaying an Image

Kivy has a couple of different image-related widgets to choose from. You can use Image to load local images from your hard drive or AsyncImage to load an image from a URL. For this example, you’ll stick with the standard Image class:

from kivy.app import App
from kivy.uix.image import Image

class MainApp(App):
    def build(self):
        img = Image(source='/path/to/real_python.png',
                    size_hint=(1, .5),
                    pos_hint={'center_x':.5, 'center_y':.5})

        return img

if __name__ == '__main__':
    app = MainApp()
    app.run()

In this code, you import Image from the kivy.uix.image sub-package. The Image class takes a lot of different parameters, but the one that you want to use is source. This tells Kivy which image to load. Here, you pass a fully-qualified path to the image. The rest of the code is the same as what you saw in the previous example.

When you run this code, you’ll see something like the following:

Showing an image with Kivy

The text from the previous example has been replaced with an image.

Now you’ll learn how to add and arrange multiple widgets in your application.

Laying Out the UI

Each GUI framework that you use has its own method of arranging widgets. For example, in wxPython you’ll use sizers, while in Tkinter you use a layout or geometry manager. With Kivy, you’ll use Layouts. There are several different types of Layouts that you can use. Here are some of the most common ones:

  • BoxLayout
  • FloatLayout
  • GridLayout

You can search Kivy’s documentation for a full list of available Layouts. You can also look in kivy.uix for the actual source code.

Try out the BoxLayout with this code:

import kivy
import random

from kivy.app import App
from kivy.uix.button import Button
from kivy.uix.boxlayout import BoxLayout

red = [1,0,0,1]
green = [0,1,0,1]
blue =  [0,0,1,1]
purple = [1,0,1,1]

class HBoxLayoutExample(App):
    def build(self):
        layout = BoxLayout(padding=10)
        colors = [red, green, blue, purple]

        for i in range(5):
            btn = Button(text="Button #%s" % (i+1),
                         background_color=random.choice(colors)
                         )

            layout.add_widget(btn)
        return layout

if __name__ == "__main__":
    app = HBoxLayoutExample()
    app.run()

Here, you import BoxLayout from kivy.uix.boxlayout and instantiate it. Then you create a list of colors, which are themselves lists of Red-Blue-Green (RGB) colors. Finally, you loop over a range of 5, creating a button btn for each iteration. To make things a bit more fun, you set the background_color of the button to a random color. You then add the button to your layout with layout.add_widget(btn).

When you run this code, you’ll see something like this:

Using a Horizontal BoxLayout in Kivy

There are 5 randomly-colored buttons, one for each iteration of your for loop.

When you create a layout, there are a few arguments you should know:

  • padding: You can specify the padding in pixels between the layout and its children in one of three ways:
    1. A four-argument list: [padding_left, padding_top, padding_right, padding_bottom]
    2. A two-argument list: [padding_horizontal, padding_vertical]
    3. A singular argument: padding=10
  • spacing: You can add space between the children widgets with this argument.
  • orientation: You can change the default orientation of the BoxLayout from horizontal to vertical.

Adding Events

Like most GUI toolkits, Kivy is mostly event-based. The framework responds to user keypresses, mouse events, and touch events. Kivy has the concept of a Clock that you can use to schedule function calls for some time in the future.

Kivy also has the concept of Properties, which works with the EventDispatcher. Properties help you do validation checking. They also let you fire events whenever a widget changes its size or position.

Let’s add a button event to your button code from earlier:

from kivy.app import App
from kivy.uix.button import Button

class MainApp(App):
    def build(self):
        button = Button(text='Hello from Kivy',
                        size_hint=(.5, .5),
                        pos_hint={'center_x': .5, 'center_y': .5})
        button.bind(on_press=self.on_press_button)

        return button

    def on_press_button(self, instance):
        print('You pressed the button!')

if __name__ == '__main__':
    app = MainApp()
    app.run()

In this code, you call button.bind() and link the on_press event to MainApp.on_press_button(). This method implicitly takes in the widget instance, which is the button object itself. Finally, a message will print to stdout whenever the user presses your button.

Using the KV Language

Kivy also provides a design language called KV that you can use with your Kivy applications. The KV language lets you separate your interface design from the application’s logic. This follows the separation of concerns principle and is part of the Model-View-Controller architectural pattern. You can update the previous example to use the KV language:

from kivy.app import App
from kivy.uix.button import Button

class ButtonApp(App):
    def build(self):
        return Button()

    def on_press_button(self):
        print('You pressed the button!')

if __name__ == '__main__':
    app = ButtonApp()
    app.run()

This code might look a bit odd at first glance, as it creates a Button without setting any of its attributes or binding it to any events. What’s happening here is that Kivy will automatically look for a file that has the same name as the class in lowercase, without the App part of the class name.

In this case, the class name is ButtonApp, so Kivy will look for a file named button.kv. If that file exists and is properly formatted, then Kivy will use it to load up the UI. Go ahead and create this file and add the following code:

 1<Button>:
 2    text: 'Press me'
 3    size_hint: (.5, .5)
 4    pos_hint: {'center_x': .5, 'center_y': .5}
 5    on_press: app.on_press_button()

Here’s what each line does:

  • Line 1 matches the Button call in your Python code. It tells Kivy to look into the instantiated object for a button definition.
  • Line 2 sets the button’s text.
  • Line 3 sets the width and height with size_hint.
  • Line 4 sets the button’s position with pos_hint.
  • Line 5 sets the on_press event handler. To tell Kivy where the event handler is, you use app.on_press_button(). Here, Kivy knows will look in the Application class for a method called .on_press_button().

You can set up all of your widgets and layouts inside one or more KV language files. The KV language also supports importing Python modules in KV, creating dynamic classes, and much more. For full details, check out Kivy’s guide to the KV Language.

Now you’re ready to create a real application!

Creating a Kivy Application

One of the best ways to learn a new skill is by creating something useful. With that in mind, you’ll use Kivy to build a calculator that supports the following operations:

  • Addition
  • Subtraction
  • Multiplication
  • Division

For this application, you’ll need a series of buttons in some kind of layout. You’ll also need a box along the top of your app to display the equations and their results. Here’s a sketch of your calculator:

Kivy Calculator Mockup

Now that you have a goal for the UI, you can go ahead and write the code:

 1from kivy.app import App
 2from kivy.uix.boxlayout import BoxLayout
 3from kivy.uix.button import Button
 4from kivy.uix.textinput import TextInput
 5
 6class MainApp(App):
 7    def build(self):
 8        self.operators = ["/", "*", "+", "-"]
 9        self.last_was_operator = None
10        self.last_button = None
11        main_layout = BoxLayout(orientation="vertical")
12        self.solution = TextInput(
13            multiline=False, readonly=True, halign="right", font_size=55
14        )
15        main_layout.add_widget(self.solution)
16        buttons = [
17            ["7", "8", "9", "/"],
18            ["4", "5", "6", "*"],
19            ["1", "2", "3", "-"],
20            [".", "0", "C", "+"],
21        ]
22        for row in buttons:
23            h_layout = BoxLayout()
24            for label in row:
25                button = Button(
26                    text=label,
27                    pos_hint={"center_x": 0.5, "center_y": 0.5},
28                )
29                button.bind(on_press=self.on_button_press)
30                h_layout.add_widget(button)
31            main_layout.add_widget(h_layout)
32
33        equals_button = Button(
34            text="=", pos_hint={"center_x": 0.5, "center_y": 0.5}
35        )
36        equals_button.bind(on_press=self.on_solution)
37        main_layout.add_widget(equals_button)
38
39        return main_layout

Here’s how your calculator code works:

  • In lines 8 to 10, you create a list of operators and a couple of handy values, last_was_operator and last_button, that you’ll use later on.
  • In lines 11 to 15, you create a top-level layout main_layout and add a read-only TextInput widget to it.
  • In lines 16 to 21, you create a nested list of lists containing most of your buttons for the calculator.
  • In line 22, you start a for loop over those buttons. For each nested list you’ll do the following:
    • In line 23, you create a BoxLayout with a horizontal orientation.
    • In line 24, you start another for loop over the items in the nested list.
    • In lines 25 to 39, you create the buttons for the row, bind them to an event handler, and add the buttons to the horizontal BoxLayout from line 23.
    • In line 31, you add this layout to main_layout.
  • In lines 33 to 37, you create the equals button (=), bind it to an event handler, and add it to main_layout.

The next step is to create the .on_button_press() event handler. Here’s what that code looks like:

41def on_button_press(self, instance):
42    current = self.solution.text
43    button_text = instance.text
44
45    if button_text == "C":
46        # Clear the solution widget
47        self.solution.text = ""
48    else:
49        if current and (
50            self.last_was_operator and button_text in self.operators):
51            # Don't add two operators right after each other
52            return
53        elif current == "" and button_text in self.operators:
54            # First character cannot be an operator
55            return
56        else:
57            new_text = current + button_text
58            self.solution.text = new_text
59    self.last_button = button_text
60    self.last_was_operator = self.last_button in self.operators

Most of the widgets in your application will call .on_button_press(). Here’s how it works:

  • Line 41 takes the instance argument so you can access which widget called the function.

  • Lines 42 and 43 extract and store the value of the solution and the button text.

  • Lines 45 to 47 check to see which button was pressed. If the user pressed C, then you’ll clear the solution. Otherwise, move on to the else statement.

  • Line 49 checks if the solution has any pre-existing value.

  • Line 50 to 52 check if the last button pressed was an operator button. If it was, then solution won’t be updated. This is to prevent the user from having two operators in a row. For example, 1 */ is not a valid statement.

  • Lines 53 to 55 check to see if the first character is an operator. If it is, then solution won’t be updated, since the first value can’t be an operator value.

  • Lines 56 to 58 drop to the else clause. If none of the previous conditions are met, then update solution.

  • Line 59 sets last_button to the label of the last button pressed.

  • Line 60 sets last_was_operator to True or False depending on whether or not it was an operator character.

The last bit of code to write is .on_solution():

62def on_solution(self, instance):
63    text = self.solution.text
64    if text:
65        solution = str(eval(self.solution.text))
66        self.solution.text = solution

Once again, you grab the current text from solution and use Python’s built-in eval() to execute it. If the user created a formula like 1+2, then eval() will run your code and return the result. Finally, you set the result as the new value for the solution widget.

When you run this code, your application will look like this on a desktop computer:

Kivy Calculator

To see the full code for this example, expand the code block below.

Here’s the full code for the calculator:

from kivy.app import App
from kivy.uix.boxlayout import BoxLayout
from kivy.uix.button import Button
from kivy.uix.textinput import TextInput

class MainApp(App):
    def build(self):
        self.operators = ["/", "*", "+", "-"]
        self.last_was_operator = None
        self.last_button = None
        main_layout = BoxLayout(orientation="vertical")
        self.solution = TextInput(
            multiline=False, readonly=True, halign="right", font_size=55
        )
        main_layout.add_widget(self.solution)
        buttons = [
            ["7", "8", "9", "/"],
            ["4", "5", "6", "*"],
            ["1", "2", "3", "-"],
            [".", "0", "C", "+"],
        ]
        for row in buttons:
            h_layout = BoxLayout()
            for label in row:
                button = Button(
                    text=label,
                    pos_hint={"center_x": 0.5, "center_y": 0.5},
                )
                button.bind(on_press=self.on_button_press)
                h_layout.add_widget(button)
            main_layout.add_widget(h_layout)

        equals_button = Button(
            text="=", pos_hint={"center_x": 0.5, "center_y": 0.5}
        )
        equals_button.bind(on_press=self.on_solution)
        main_layout.add_widget(equals_button)

        return main_layout

    def on_button_press(self, instance):
        current = self.solution.text
        button_text = instance.text

        if button_text == "C":
            # Clear the solution widget
            self.solution.text = ""
        else:
            if current and (
                self.last_was_operator and button_text in self.operators):
                # Don't add two operators right after each other
                return
            elif current == "" and button_text in self.operators:
                # First character cannot be an operator
                return
            else:
                new_text = current + button_text
                self.solution.text = new_text
        self.last_button = button_text
        self.last_was_operator = self.last_button in self.operators

    def on_solution(self, instance):
        text = self.solution.text
        if text:
            solution = str(eval(self.solution.text))
            self.solution.text = solution


if __name__ == "__main__":
    app = MainApp()
    app.run()

It’s time to deploy your application!

Packaging Your App for Android

Now that you’ve finished the code for your application, you can share it with others. One great way to do that is to turn your code into an application that can run on your Android phone. To accomplish this, first you’ll need to install a package called buildozer with pip:

Then, create a new folder and navigate to it in your terminal. Once you’re there, you’ll need to run the following command:

This will create a buildozer.spec file that you’ll use to configure your build. For this example, you can edit the first few lines of the spec file as follows:

[app]

# (str) Title of your application
title = KvCalc

# (str) Package name
package.name = kvcalc

# (str) Package domain (needed for android/ios packaging)
package.domain = org.kvcalc

Feel free to browse the rest of the file to see what else you can change.

At this point, you’re almost ready to build your application, but first, you’ll want to install the dependencies for buildozer. Once those are installed, copy your calculator application into your new folder and rename it to main.py. This is required by buildozer. If you don’t have the file named correctly, then the build will fail.

Now you can run the following command:

$ buildozer -v android debug

The build step takes a long time! On my machine, it took 15 to 20 minutes. Depending on your hardware, it may take even longer, so feel free to grab a cup of coffee or go for a run while you wait. Buildozer will download whatever Android SDK pieces it needs during the build process. If everything goes according to plan, then you’ll have a file named something like kvcalc-0.1-debug.apk in your bin folder.

The next step is to connect your Android phone to your computer and copy the apk file to it. Then you can open the file browser on your phone and click on the apk file. Android should ask you if you’d like to install the application. You may see a warning since the app was downloaded from outside Google Play, but you should still be able to install it.

Here’s the calculator running on my Samsung S9:

Kivy Calculator Running on Android Phone

The buildozer tool has several other commands you can use. Check out the documentation to see what else you can do.

You can also package the app using python-for-android if you need more fine-grained control. You won’t cover this here, but if you’re interested, check out the project’s quickstart.

Packaging Your App for iOS

The instructions for building an application for iOS are a bit more complex than Android. For the most up-to-date information, you should always use Kivy’s official packaging documentation. You’ll need to run the following commands before you can package your application for iOS on your Mac:

$ brew install autoconf automake libtool pkg-config
$ brew link libtool
$ sudo easy_install pip
$ sudo pip install Cython==0.29.10

Once those are all installed successfully, you’ll need to compile the distribution using the following commands:

$ git clone git://github.com/kivy/kivy-ios
$ cd kivy-ios
$ ./toolchain.py build python3 kivy

If you get an error that says iphonesimulator can’t be found, then see this StackOverflow answer for ways to solve that issue. Then try running the above commands again.

If you run into SSL errors, then you probably don’t have Python’s OpenSSL setup. This command should fix that:

$ cd /Applications/Python 3.7/
$ ./Install Certificates.command

Now go back and try running the toolchain command again.

Once you’ve run all the previous commands successfully, you can create your Xcode project using the toolchain script. Your main application’s entry point must be named main.py before you create the Xcode project. Here is the command you’ll run:

./toolchain.py create <title> <app_directory>

There should be a directory named title with your Xcode project in it. Now you can open that project in Xcode and work on it from there. Note that if you want to submit your application to the App Store, then you’ll have to create a developer account at developer.apple.com and pay their yearly fee.

Packaging Your App for Windows

You can package your Kivy application for Windows using PyInstaller. If you’ve never used it before, then check out Using PyInstaller to Easily Distribute Python Applications.

You can install PyInstaller using pip:

$ pip install pyinstaller

The following command will package your application:

This command will create a Windows executable and several other files. The -w argument tells PyInstaller that this is a windowed application, rather than a command-line application. If you’d rather have PyInstaller create a single executable file, then you can pass in the --onefile argument in addition to -w.

Packaging Your App for macOS

You can use PyInstaller to create a Mac executable just like you did for Windows. The only requirement is that you run this command on a Mac:

$ pyinstaller main.py -w --onefile

This will create a single file executable in the dist folder. The executable will be the same name as the Python file that you passed to PyInstaller. If you’d like to reduce the file size of the executable, or you’re using GStreamer in your application, then check out Kivy’s packaging page for macOS for more information.

Conclusion

Kivy is a really interesting GUI framework that you can use to create desktop user interfaces and mobile applications on both iOS and Android. Kivy applications will not look like the native apps on any platform. This can be an advantage if you want your application to look and feel different from the competition!

In this tutorial, you learned the basics of Kivy including how to add widgets, hook up events, lay out multiple widgets, and use the KV language. Then you created your first Kivy application and learned how to distribute it on other platforms, including mobile!

There are many widgets and concepts about Kivy that you didn’t cover here, so be sure to check out Kivy’s website for tutorials, sample applications, and much more.

Further Reading

To learn more about Kivy, check out these resources:

  • Kivy Programming Guide
  • Kivy Packaging Documentation
  • Build Desktop GUI Apps Using Python

To see how you might create a desktop application with another Python GUI framework, check out How to Build a Python GUI Application With wxPython.

Watch Now This tutorial has a related video course created by the Real Python team. Watch it together with the written tutorial to deepen your understanding: Build Cross-Platform GUI Apps With Kivy

The overall process for creating a package for iOS can be explained in 4 steps:

  1. Compile the distribution (python + modules for iOS)

  2. Create an Xcode project (and link your source code)

  3. Update the Xcode project

  4. Customize the Xcode project

Prerequisites¶

You need to install some dependencies, like Cython, autotools, etc. We
encourage you to use Homebrew to install
those dependencies:

$ brew install autoconf automake libtool pkg-config
$ brew link libtool
$ pip install Cython==0.29.28

For more detail, see iOS Prerequisites.
Just ensure that everything is ok before starting the second step!

Compile the distribution¶

Open a terminal, and type:

$ pip install kivy-ios
$ toolchain build kivy

If you experience any issues, please refer to our
user group or the
kivy-ios project page.

Create an Xcode project¶

Before proceeding to the next step, ensure your application entry point is a file
named main.py.

We provide a script that creates an initial Xcode project to start with. In the
command line below, replace title with your project name. It must be a
name without any spaces or illegal characters:

$ toolchain create <title> <app_directory>
$ toolchain create Touchtracer ~/code/kivy/examples/demo/touchtracer

Note

You must use a fully qualified path to your application directory.

A directory named <title>-ios will be created, with an Xcode project in it.
You can open the Xcode project:

$ open touchtracer-ios/touchtracer.xcodeproj

Then click on Play, and enjoy.

Note

Everytime you press Play, your application directory will be synced to
the <title>-ios/YourApp directory. Don’t make changes in the -ios
directory directly.

Update the Xcode project¶

Let’s say you want to add numpy to your project but you did not compile it
prior to creating your XCode project. First, ensure it is built:

Then, update your Xcode project:

$ toolchain update touchtracer-ios

All the libraries / frameworks necessary to run all the compiled recipes will be
added to your Xcode project.

Customize the Xcode project¶

There are various ways to customize and configure your app. Please refer
to the kivy-ios documentation
for more information.

Known issues¶

All known issues with packaging for iOS are currently tracked on our
issues page. If you encounter
an issue specific to packaging for iOS that isn’t listed there, please feel
free to file a new issue, and we will get back to you on it.

While most are too technical to be written here, one important known issue is
that removing some libraries (e.g. SDL_Mixer for audio) is currently not
possible because the kivy project requires it. We will fix this and others
in future versions.

FAQ¶

Application quit abnormally!¶

In debug mode, all the print statements are sent to the Xcode console.
Looking and grep’ing these logs is highly encouraged. You’ll probably find
that you missed to build/install a required dependency. Not your case?
Feel free to ask on our Discord support channels.

How can Apple accept a python app?¶

We managed to merge the app binary with all the libraries into a single binary,
called libpython. This means all binary modules are loaded beforehand, so
nothing is dynamically loaded.

Have you already submitted a Kivy application to the App store?¶

Yes, absolutely. Kivy Apps in the Apple App Store.

Welcome to python app development for beginners where we will be building a cross platform mobile app and desktop gui app using the python kivy framework. For those who don’t know what kivy is.

Kivy is a python framework which allows us to create one code set in python and then port that code to multiple platforms. Such as mobile both android and ios.

We can port the code to macos, linux and windows. Which makes it versatile in helping us build cross platform apps.

Also for the longest time the python community didn’t have many options for python mobile app development. With kivy this has opened a whole lot of doors for the python community. To start releasing mobile apps, mobile games, cross platform gui applications using python.

Let us begin by kicking off this python application development tutorial. We won’t just be covering regular desktop apps, but also will be covering python mobile app development.

So in this beginners tutorial we will be learning the following about the kivy framework.

  • Setting up the kivy framework in your python environment.
  • Adding UI elements to our kivy app.
  • Event handling.
  • Database interaction.
  • Laying out UI elements.
  • Compiling to various platforms like android, ios, macos, linux and windows.

Some important things to know about kivy. If you are looking for the full native experience using the kivy framework on mobile devices. You may be a little dissapointed.

Since kivy doesn’t directly integrate into these apis, it uses its own form of canvas which can render ui on mobile devices, but they will not be in the native style by default.

For this reason kivy might not be the best candidate for mobile apps which will be consumer facing. Kivy can be very useful for technical implementations however.

Where you want to use your existing python skills to go and build an app which can just look consistent on all platforms you deploy it on. If you are wanting to build the next spotify with beautiful design elements.

Then kivy probably won’t be the best candidate. Then you may want to look at technologies like react native, ionic, flutter or completely native with kotlin/java or swift/objective-c.

Obviously you need to assess all technologies you use for your specific use case at the end of the day.

Some assumptions before kivy installation

For this tutorial I will be making a few assumptions. That you one have some very basic knowledge of python and that you know how to manage virtual environments in python.

Since kivy is built on quite a few other python libraries we need to create a safe environment. Where we can install the different python libraries which kivy depend on.

So I will start the tutorial by assuming you have already installed python on your environment. Whether that be windows, linux or macos.

Python app development – what we are building

So let’s talk about what we will be building. We going to build a basic task manage using kivy. We will be able to add tasks, remove tasks, mark them as complete.

Then we going to build it to android,ios,windows,linux and macos. If there is some additional time we may even build this to raspberry pi. Here is a bit of a rough drawing of what we will be building for this tutorial.

python app development for beginners using kivy - task manager

Python app development tutorial for beginners – basic task manager app

So our application will consist of add task button. Then a list of tasks with basic descriptions, a tick box for marking a task as done and a X button for deleting a task.

So I will be building this application in ubuntu linux, but you can use whatever operating system you are comfortable with. Some operating systems the installation procedure might be slightly different.

So feel free to just read up on your development environment. Ubuntu should be quite similar to the procedure on mac, but on windows you may need to follow a slightly different installation procedure.

Once we have installed we just going to create a very basic set of examples to get you more comfortable with kivy. Then we will start building out our task manager app.

Python app development – Kivy Installation

Prefer video check out this video where we fix the issues and install as we go along:

Let us first start by setting up a basic virtual environment. If you don’t know how python virtual environments work here is a quick explanation. Python virtual environments, allow you to install dependencies in a folder.

Then you can load this folder up as your default environment to run your python application from. This just avoids having to deal with dependency conflicts in your project.

Which allows you to tailor your project to that specific environment. So here is how you can create a python virtual environment.

If you are using linux like me you need to install the python virtual environment. So run this to install it in a terminal window.

sudo apt-get install python3-venv

In a terminal window run this command.

python3 -m venv kivyplayground

When you execute this python will create a new virtual environment for you in your kivyplayground folder. Now the next thing you will see if you cd into this folder is this.

Python app development tutorial for beginners – creating the venv

So as you can see this command has created a full new environment for us with our own pip3 and python3 binary.

Pretty cool hey? So let’s now get to the point of activating our environment and installing kivy. To activate this environment you run this command on the terminal.

source bin/activate

Once you have run that you will see the terminal change into your virtual environment like this.

Python app development tutorial for beginners – python activate virtual environment

We now are in a safe virtual environment where we can install kivy without having to worry about conflicting dependencies. To install kivy run this command on the terminal.

python -m pip install kivy

So in linux you might get some errors like this.

Python app development tutorial for beginners – errors installing kivy

This is actually an issue within ubuntu. If you are also using ubuntu you can install using this command instead. If you are using macos the above command should work just fine.

sudo apt-get install python3-kivy

So the above will fix it for your main python environment but not for your virtual one.You will likely still not quite be able to run kivy yet on linux. So you will need to install a few more dependencies.

sudo apt install libsdl2-image-dev libsdl2-ttf-dev libsdl2-mixer-dev libpango1.0-dev 

Then you will need gstreamer as well so to install that you run a command.

sudo apt-get install -y 
    python-pip 
    build-essential 
    git 
    python 
    python-dev 
    ffmpeg 
    libsdl2-dev 
    libsdl2-image-dev 
    libsdl2-mixer-dev 
    libsdl2-ttf-dev 
    libportmidi-dev 
    libswscale-dev 
    libavformat-dev 
    libavcodec-dev 
    zlib1g-dev

sudo apt-get install -y 
    libgstreamer1.0 
    gstreamer1.0-plugins-base 
    gstreamer1.0-plugins-good

pip3 install wheel cython tokenizer
sudo apt-get install build-essential libev4 libev-dev cython3 python-setuptools

So the issue we have in ubuntu is that the dependencies don’t always line up. So we will now compile kivy from source by running the following command.

pip install git+https://github.com/kivy/kivy.git@master

It will now take quite a while to compile so give it about 20 mins to complete. At the end you should have something like this.

Python app development tutorial for beginners – compiling kivy

We can now finally start using kivy within ubuntu. If you are using macos and windows this process should be as simple as just running pip install kivy. However I thought I would do the ubuntu version to show you how to handle a more difficult installation.

Let us now look at the most basic code we can write to get a kivy window going with a basic label widget. I will use visual studio code to edit the code but you can use any editor you like.

Kivy most basic app code example

So we will create a basic app now which just says hello world and changes the title of the window. You can copy this code below and just call it main.py.

from kivy.app import App
from kivy.uix.label import Label

class KivyApp(App):
    def build(self):
        self.title = "Test app"
        label = Label(text='Hello world app',
                      size_hint=(.1, .1),
                      pos_hint={'center_x': .1, 'center_y': .1})

        return label

if __name__ == '__main__':
    app = KivyApp()
    app.run()

Save it off and run it by typing:

python main.py

On the command line and hit enter. You should now end up with something which looks like this.

Python app development tutorial for beginners – basic kivy example

So a very quick overview of how the code works. So Kivy has a main app class which implements the build method. The build method takes widgets in kivy and compiles them together then returns a context.

In our basic first app we just return a basic label. We also set the title by calling self.title = “Test app”. So the great thing about Kivy is it is designed to use separation of concerns.

Which means you can build customer widgets by using the opengl library or use existing kivy widgets to build another one.

You can then use these widgets to add to your build method making it just alot easier to put together apps. Once you have all your widgets created.

So in this tutorial we will take an iterative approach to creating our widgets. So we will start with laying them out in a simple way then we will improve them until our app looks to be working smoothly.

This is so that we can get to the point of creating the basic layout of our app quicker. Then later just adjusting the widgets to make things work in a better way.

So before we start on building our task manager app let’s learn about KV files. So KV files are a separate language which is a lot like YAML which is a simplified way of creating widget templates.

You can also override behavior of current widgets. To do this all you need to do is define an all lowercase file with the class name of the widget as filename and the extension .kv in your project.

This will override the properties of that widget. Let us create something simple in regular kivy then convert that to kv language.

Kivy KV language – python app development

So for this we will create a basic login screen which expects a username and a password. A very common screen you might see in any app. So here is what the code looks like.

from kivy.app import App
from kivy.uix.label import Label
from kivy.uix.textinput import TextInput
from kivy.uix.gridlayout import GridLayout
from kivy.uix.boxlayout import BoxLayout
from kivy.uix.button import Button
from kivy.core.window import Window

class KivyApp(App):
    def build(self):
        self.title = "Login Screen"
        Window.size = (400,200)
        layout = GridLayout(cols=2,rows=2,padding=10,spacing=10,row_default_height=30)
        
        usernameinput = TextInput()
        passwordinput = TextInput(password=True)
        usernamelbl = Label(text="Username",size_hint_x=None, width=100)
        
        passwordlbl = Label(text="Password",size_hint_x=None, width=100)
        
        layout.add_widget(usernamelbl)
        layout.add_widget(usernameinput)
        layout.add_widget(passwordlbl)
        layout.add_widget(passwordinput)
     
        main_layout = BoxLayout(orientation='vertical',padding=10,spacing=10)
        main_layout.add_widget(layout)

        loginbutton = Button(text="Login")
        

        main_layout.add_widget(loginbutton)

        return main_layout

if __name__ == '__main__':
    app = KivyApp()
    app.run()

So if you run this code you will end up with a nice login window like this.

Python app development tutorial for beginners – login screen example

So let’s now talk about the code involved in creating this window. First we import a bunch of widgets, TextInput,GridLayout,BoxLayout,Label,Window and Button.

TextInput is basically a text input box for the user to type into. GridLayout allows us to define a layout in terms of rows and columns much like a table. BoxLayout has boxes either in the horizonatal or vertical direction which resizes to the full window.

Label is for our username and password text next to our textinput field. Window we use to resize our window and finally the button widget is for our login button. So let’s now go through the code.

We set our window title to login screen. Then we set our window size to 400 pixels wide and 200 pixel high. This gives us a nice size for our login window.

Next we define a grid layout with 2 rows and 2 columns. So the first 2 columns in our first row will contain our username label and our username input field. We also define a padding and spacing property and a max line height for our grid. Just to allow our widgets to be spaced nicely.

Next we define ourselves a widget for our username and password with the flag password=True so that the input is a masked field. We also define our labels for our textinput fields.

We then define a boxlayout which will be in the vertical direction. So we are going to add our grid layout to have our username and password fields and labels.

Then we add our login button to our box layout as well because we want it be a spanned button over the 2 columns from our grid layout. Then we simply return the main_layout as the context to be rendered.

With all this we get this nice login screen.

Let’s now look at how we can simplify by using a KV file. Here is what the KV language version would look like.

BoxLayout:
    orientation: 'vertical'
    padding: 10
    spacing: 10
    GridLayout:
        rows: 2
        cols: 2
        padding: 10
        spacing: 10
        row_default_height: 30
        Label:
            text: 'Username'
        TextInput:
        Label:
            text: 'Password'
        TextInput:
            password: True
    Button:
        text: 'Login'

Save that off as login.kv. Then here is the python code that will load this by inference.

from kivy.app import App
from kivy.uix.label import Label
from kivy.uix.textinput import TextInput
from kivy.uix.gridlayout import GridLayout
from kivy.uix.boxlayout import BoxLayout
from kivy.uix.button import Button
from kivy.core.window import Window
from kivy.lang import Builder


class LoginApp(App):
    def build(self):
        self.title = "Login Screen"
        Window.size = (400,200)
        pass

if __name__ == '__main__':
    LoginApp().run()

With this method we can turn any KV file into a widget which can be re used in our application. So for our task manager app you can see how we can easily try to define some KV data then load that up into our app to be displayed.

Let’s just do something fun quick and modify our window background so our login screen is little bit styled.

class LoginApp(App):
    def build(self):
        self.title = "Login Screen"
        Window.size = (400,200)
        Window.clearcolor = (0.6,0.6,0.6,1)
        pass

if __name__ == '__main__':
    LoginApp().run()

With that we just change our color to a different gray on our background using the clear color property on our window object.

This is now all good and well but let’s do something with this. Let’s make our login button do something.

I think a great idea is to make our button work then we login using a rest api. Let us look at doing that. This next section will teach you about bindings and events.

In this section we are going to call the api.

https://reqres.in/api/login

Which will allow us to post the contents of our username and password to the rest api and login to our app. Don’t worry this isn’t for nothing we will still be using our login screen in our task manager application.

So let’s quickly look at how we can just get our button to do something. Then we can look at having it call the rest api after that.

So let’s add our first event. This so simple all we need to do is add and on_press event in our kv file and create a new method in our python file. Here is what it looks like.

BoxLayout:
    orientation: 'vertical'
    padding: 10
    spacing: 10
    GridLayout:
        rows: 2
        cols: 2
        padding: 10
        spacing: 10
        row_default_height: 30
        Label:
            text: 'Username'
        TextInput:
        Label:
            text: 'Password'
        TextInput:
            password: True
    Button:
        text: 'Login'
        on_press: app.login_button_action()
from kivy.app import App
from kivy.uix.label import Label
from kivy.uix.textinput import TextInput
from kivy.uix.gridlayout import GridLayout
from kivy.uix.boxlayout import BoxLayout
from kivy.uix.button import Button
from kivy.core.window import Window
from kivy.lang import Builder


class LoginApp(App):
    def build(self):
        self.title = "Login Screen"
        Window.size = (400,200)
        Window.clearcolor = (0.6,0.6,0.6,1)
        pass
    def login_button_action(self):
        print("Login")
if __name__ == '__main__':
    LoginApp().run()

So we added two things here.

on_press: app.login_button_action()
   def login_button_action(self):
        print("Login")

So if you now run this and you it login. You should get login printing in your console.

python app development tutorial events with kivy

Let’s now do a little more with our app and actually use our login form to verify a login session with the api from earlier.

Python app development tutorial – logging in with a rest api

In this section we will import the requests library and the json library and make a call to our api. Then get back the response and print it out.

The first thing we will do is just make sure we can get a good response back. So we will hard code the email and password. Here is what the code looks like.

from kivy.app import App
from kivy.uix.label import Label
from kivy.uix.textinput import TextInput
from kivy.uix.gridlayout import GridLayout
from kivy.uix.boxlayout import BoxLayout
from kivy.uix.button import Button
from kivy.core.window import Window
from kivy.lang import Builder
import requests
import json

class LoginApp(App):
    def build(self):
        self.title = "Login Screen"
        Window.size = (400,200)
        Window.clearcolor = (0.6,0.6,0.6,1)
        pass
    def login_button_action(self):
        url = 'https://reqres.in/api/login'
        data = json.dumps({"email": "eve.holt@reqres.in","password": "cityslicka"})
        response = requests.post(url, data=data, headers={'Content-Type':'application/json'})
        
        print(response.text)
if __name__ == '__main__':
    LoginApp().run()

So let’s talk about what is going on in the this code. We first import the requests and json classes. We then in our event method define our api url and set url to the rest api url.

We then set our dictionary which contains our credentials and finally dump it as json into our data variable. After that we do a post request to the rest api and set the response.

We finally then print out the response text. Here is what you should be getting if you click on the login button.

python app development tutorial for beginners - login screen token test

You should now get a login token. Which means we have successfully logged in. Let’s now implement this to take the input on our login screen to login. To do this we need to get the username value and password value.

So we need to set ids in our kv file and use them in our login.py. Here is the full code.

BoxLayout:
    orientation: 'vertical'
    padding: 10
    spacing: 10
    GridLayout:
        rows: 2
        cols: 2
        padding: 10
        spacing: 10
        row_default_height: 30
        Label:
            text: 'Username'
        TextInput:
            id: usernamevalue
        Label:
            text: 'Password'
        TextInput:
            id: passwordvalue
            password: True
    Button:
        text: 'Login'
        on_press: app.login_button_action()
from kivy.app import App
from kivy.uix.label import Label
from kivy.uix.textinput import TextInput
from kivy.uix.gridlayout import GridLayout
from kivy.uix.boxlayout import BoxLayout
from kivy.uix.button import Button
from kivy.core.window import Window
from kivy.lang import Builder
import requests
import json

class LoginApp(App):
    def build(self):
        self.title = "Login Screen"
        Window.size = (400,200)
        Window.clearcolor = (0.6,0.6,0.6,1)
        pass
    def login_button_action(self):
        url = 'https://reqres.in/api/login'
        #data = json.dumps({"email": "eve.holt@reqres.in","password": "cityslicka"})
        data = json.dumps({"email": self.root.ids.usernamevalue.text,"password": self.root.ids.passwordvalue.text})
        response = requests.post(url, data=data, headers={'Content-Type':'application/json'})

        print(response.text)
if __name__ == '__main__':
    LoginApp().run()

So the only different here now is we use self.root.ids.usernamevale and passwordvalue respectively which we defined in our kv file. Now we use the textinput fields to login.

You should now be able to get this output.

python app development tutorial for beginners - test login with rest api

So let’s very quickly implement this login so it can fail with wrong credentials and change the screen with successful credentials.

So you probably thinking how the heck are we going to do that. Well that comes to our next section which is the screenmanager.

This will help us transition between multiple screens. We will also be simplifying our app by bringing all our widgets into a single python file. Here is how it will work we will define all our kv language code in a builder string.

Then create classes for each which will represent our screens then we will transition between them. This is where it get’s interesting. We will build out our task screen and more.

Python app development tutorial – screenmanager transitions

Let’s once again start off simple let’s create a screen for a successful login and a failed login. To start we will create the failed login screen. So start with a new python file called main.py. Here is the code.

from kivy.app import App
from kivy.lang import Builder
from kivy.uix.screenmanager import ScreenManager, Screen
import json
import requests

Builder.load_string("""
<LoginScreen>:
    BoxLayout:
        orientation: 'vertical'
        padding: 10
        spacing: 10
        GridLayout:
            rows: 2
            cols: 2
            padding: 10
            spacing: 10
            row_default_height: 30
            Label:
                text: 'Username'
            TextInput:
                id: usernamevalue
            Label:
                text: 'Password'
            TextInput:
                id: passwordvalue
                password: True
        Button:
            text: 'Login'
            on_press: root.login_button_action()

<FailedLoginScreen>:
    BoxLayout:
        orientation: 'vertical'
        Label:
            text: 'Failed Login'
        Button:
            text: 'Back to login'
            on_press: root.manager.current = 'login'
""")


class LoginScreen(Screen):
    def build(self):
        pass
 
    def login_button_action(self):
        url = 'https://reqres.in/api/login'
        
    
        #data = json.dumps({"email": "eve.holt@reqres.in","password": "cityslicka"})
        data = json.dumps({"email": self.ids.usernamevalue.text,"password": self.ids.passwordvalue.text})
        
        response = requests.post(url, data=data, headers={'Content-Type':'application/json'})

        userdata = json.loads(response.text)

        if userdata.get("token"):
            print("Logging in")
        else:
            self.manager.current = 'failedlogin'


class FailedLoginScreen(Screen):
    pass


sm = ScreenManager()
sm.add_widget(LoginScreen(name='login'))
sm.add_widget(FailedLoginScreen(name='failedlogin'))

class MainApp(App):

    def build(self):
        self.title = "Task Manager"
        return sm

if __name__ == '__main__':
    MainApp().run()

Let us talk about this code. In our imports we now import the screenmanager which manages all the screens within our app. We import json and requests to allow our interaction with the rest api and parsing json to and from dictionaries.

We then use the Builder class to define our kv language structure for our login screen and our failedlogin screen. So this we now need 2 classes one for our failedloginscreen and our loginscreen.

So basically widgets are classes and classes get defined in a KV file as <ClassName>: so in our kv language portion we define our <LoginScreen> and our <FailedLoginScreen>.

Then in our python code we define our loginscreen class and it does a few things. It set’s the url of our api call, does a post request to our login api and then goes and uses the response to verify if we got a token back.

If we did not we transition to the failed login screen. In our main portion of our app we register the screens with our screenmanager and in the build method in MainApp we just return the screenmanager as the render context.

Here is what the app looks like. I know a little ugly but so far it works.

python app development tutorial for beginners - login screens

python app development tutorial for beginners -  kivy login screen

In our failedlogin kv language section we define the back to login button to transition back to our login screen. So, so far so good. We will in the next section start using kivy-md to make this look a little nicer.

We now need to build out a screen which displays tasks and a screen which allows us to add a task. We need to make a choice for a database also which will run on a mobile device.

We could probably use sqlite database, but we will keep it simple. We will use either a dictionary store or a json store.

Adding more screens with kivymd

Before we do any storage let us put together our screens with mockup data. If you are just starting out with app development. It is a good idea to lay it out with test data. Just to understand how your app will work.

If you are more experienced at building apps you probably don’t need to do that. Let us add our screens and KV language and just add some buttons to our login screen so we can test quite quickly.

So we now understand how the screen manager works. So let us do something a little more mobile app friendly now. Let’s learn about kivy-md or kivy material design.

This will help us construct our app so it just looks way more professional. To use kivy-md you need to open up a terminal or command prompt again and run this command.

python3 -m pip install kivymd

python app development tutorial for beginners -  kivy md or material design setup

So let’s convert our current screens to kivy-md. Here is the full code.

from kivy.app import App
from kivy.lang import Builder
from kivy.uix.screenmanager import ScreenManager, Screen
from kivy.uix.boxlayout import BoxLayout
from kivymd.app import MDApp
from kivymd.uix.screen import MDScreen
from kivymd.uix.list import OneLineListItem
import json
import requests

Builder.load_string("""
<LoginScreen>:
    BoxLayout:
        orientation: 'vertical'
        padding: 10
        spacing: 10
        GridLayout:
            rows: 3
            cols: 1
            padding: 10
            spacing: 10
            row_default_height: 30
            MDTextField:
                hint_text: "Email"
                id: usernamevalue
            MDTextField:
                hint_text: "Password"
                id: passwordvalue
                password: True
            MDRectangleFlatButton:
                text: 'Login'
                on_press: root.login_button_action()
<FailedLoginScreen>:
    BoxLayout:
        orientation: 'vertical'
        padding: 10
        spacing: 10
        MDLabel:
            text: "Login Failed"
        MDRectangleFlatButton:
            text: 'Back To Login'
            on_press: root.manager.current = 'login'
<TaskScreen>:
    MDList:
        id: tasklist
""")

class FailedLoginScreen(Screen):
    pass


class TaskScreen(Screen):
    def on_enter(self):
        for i in range(20):
            self.ids.tasklist.add_widget(
                OneLineListItem(text=f"Filler task {i}")
            )


class LoginScreen(Screen):
    def build(self):
        pass
 
    def login_button_action(self):
        url = 'https://reqres.in/api/login'
        
        #data = json.dumps({"email": "eve.holt@reqres.in","password": "cityslicka"})
        data = json.dumps({"email": self.ids.usernamevalue.text,"password": self.ids.passwordvalue.text})

        response = requests.post(url, data=data, headers={'Content-Type':'application/json'})

        userdata = json.loads(response.text)

        if userdata.get("token"):
            self.manager.current = 'tasklist'
        else:
            self.manager.current = 'failedlogin'


class MainApp(MDApp):

    def build(self):
        sm = ScreenManager();
        sm.add_widget(LoginScreen(name='login'))
        sm.add_widget(FailedLoginScreen(name='failedlogin'))
        sm.add_widget(TaskScreen(name='tasklist'))

        return sm

if __name__ == '__main__':
    MainApp().run()

If you execute this you will have this functionality so far.

python app development tutorial for beginners - kivy material design login screen

python app development for beginners tutorial – login screen
python app development tutorial for beginners -  kivy material design login screen failed login python app development tutorial
python app development for beginner tutorial – failed login screen
python app development tutorial for beginners -  kivy material design task list python app development tutorial
python app development for beginners tutorial – task list screen

So as you can see starting to look a lot more like a mobile app. Now let’s talk about the code quick then we will start building out additional functionality.

So we have now gone and imported kivymd. Next we imported MDApp and MDScreen. So not much has changed otherwise, we have renamed some of the dependencies we inject.

To Screen and MDApp respectively. We have included a life cycle method in our TaskScreen class which will just populate some random tasks for us.

As kivymd onelistitems, then we have also changed out our TextInput in our KV language section to MDTextField and also we have added kivy md buttons by changing out Button with MDRectangleFlatButton.

Our screenmanager mainly has been unchanged we just moved it inside of our App class so we can make sure MDApp is instantiated before we try to control our screens.

So with just a few adjustments we have made our python app look just like a mobile app. We now want to work on our task screen a little more.

For now our login screen and failed login screen is working fine. You may want to just change it up a little bit to look the way you want it. However the rest of the focus from here will be on the task screen.

Adding floating buttons and add task screen

So for our new task screen we will just add a input field and a button. Like this. Here is the KV language changes.

<TaskScreen>:
    ScrollView:
        MDList:
            id: tasklist
    MDFloatingActionButton:
        icon: "plus"
        md_bg_color: app.theme_cls.primary_color
        x: root.width - self.width - dp(10)
        y: dp(10)
        on_press: root.manager.current = 'addtask'
<AddTaskScreen>:
    BoxLayout:
        orientation: 'vertical'
        padding: 10
        spacing: 10
        GridLayout:
            rows: 3
            cols: 1
            padding: 10
            spacing: 10
            row_default_height: 30
            MDTextField:
                hint_text: "Task Name"
                id: taskname
            MDRectangleFlatButton:
                text: 'Add Task'
                on_press: root.add_task()
<ListItemWithCheckbox>:

    IconLeftWidget:
        icon: root.icon

    RightCheckbox:

So we have added the MDFloatingActionButton, we using the plus icon and the default theme color. Then x and y we setting and calculating so we can place the button at the bottom right corner of our screen.

We add a screen transition for our new screen called AddTaskScreen. The add task screen just has a box layout with a grid layout inside of it. Then we add a text field for the task name and finally just a button with an event to add the task.

We also add a custom checkbox for our list item with a icon. Here is how we modified our python code to now have a checkbox for, making our task complete.

Also some code for persisting our task list to a json file as well as being able to add task.

db = JsonStore("tasks.json")

class ListItemWithCheckbox(OneLineAvatarIconListItem):
    pass

    icon = StringProperty("android")


class RightCheckbox(IRightBodyTouch, MDCheckbox):
    pass


class FailedLoginScreen(Screen):
    pass

class AddTaskScreen(Screen):
    def add_task(self):
        db.put(uuid.uuid1().int, name= self.ids.taskname.text)    
        self.manager.current = 'tasklist'

class TaskScreen(Screen):
    def on_pre_enter(self):
        self.ids.tasklist.clear_widgets()
        for key,item in db.find():
            self.ids.tasklist.add_widget(
               ListItemWithCheckbox(text=f"{item.get('name')}",icon='pen')
            )

If you run this code you now finally end up with a nice app which can manage tasks.

We have successfully implemented our task app now we want to build it for different mobile devices.

Python app development tutorial – building for Android

To able to build for android we need to use a python tool called buildozer. To install buildozer you need to use pip again here is the command you will run on the command line or terminal.

pip install buildozer

Once buildozer is installed you want to initialize a buildozer config. To do that run.

buildozer init

That will create a buildozer.spec file which will allow you to configure your app build settings. Edit buildozer.spec and paste this into your editor.

[app]

title = GPTaskList
package.name = gptasklist
package.domain = org.gptasklist

Remember earlier on where I said you should make your python file main.py. Well this is now where that becomes important for buildozer to build your project. Make sure your python file is called main.py and run the following command.

buildozer -v android debug

Give it some time to package your apk file. Once done transfer it to your android device and install it. Simple right let’s now look at the steps involved in packaging your python app on ios.

Python app: building for ios

For ios there are just a few more steps, but nothing too crazy. First you just need to make sure you have these dependencies for the build installed.

brew install autoconf automake libtool pkg-config
brew link libtool
sudo easy_install pip
sudo pip install Cython==0.29.10

Clone the repo to help with the build.

 git clone git://github.com/kivy/kivy-ios
 cd kivy-ios
 ./toolchain.py build kivy

You can now run this to create your xcode project.

./toolchain.py create gptasklist .

Again make sure your python file is called main.py. Open up the xcode project in xcode with this command.

open gptasklist-ios/gptasklist.xcodeproj

You can now simply press the play button to build and compile your project.

Final thoughts

So you can see how easily you can build a mobile app with python just by using kivy and kivymd. I hope this python mobile app example was useful. Kivy’s simplistic code makes it really easy to put together basic apps.

I personally like this approach for creating quick and dirty projects. Kivy may even be a great way to quickly put together mvp examples. With more structure in your code you could create more complex apps.

Also the great benefit is that your kivy code can double up as a MacOS, Linux or Windows GUI application. Which may make it really useful for your specific use case. In summary Kivy is an extremely useful library.

If you wish to explore it further check out the full Kivy documentation here:

https://kivy.org/doc/stable/api-kivy.html

If you are interested in more programming tutorials. I cover alot of different topics on my blog. Why not check out some of these recent articles.

If you prefer watching video why not check out my youtube channel here: https://www.youtube.com/channel/UC1i4hf14VYxV14h6MsPX0Yw

Планшет iPad от компании Apple — всем известное и не нуждающееся в рекламе устройство. Но очень часто хочется использовать всю мощь этого устройства не только для игр и развлечения, а для серьёзной работы. Например для написания программ. Несмотря на 4-x летнею историю развития этого гаджета и наличие разных моделей удобных сред для программирования под iOS существует крайне мало. (Сразу оговорюсь сразу, во избежании дальнейшей путаницы: программирование на iOS — значит написание кода и запуск программы на iPad или iPhone, а программирование для iOS — написание приложения, которое может быть выложено в App Store.)

Pythonista. Пишем на Python для iOS

Недавно я наткнулся на великолепную программку Pythonista, которая позволяет писать на iOS для iOS.

Краткое описание

Как пишут создатели этой программы:

Pythonista brings the Zen of Python™ to your iPad or iPhone.

И это действительно так. Программа является лучшим компилятором для Python.

На мой взгляд, лучшим это приложение делают 3 вещи:

  • Не нужно интернет-подключение для запуска программы. iPad действительно становиться рабочей станцией;
  • Есть всплывающие подсказки и встроенная документация (опять же без доступа к интернету);
  • И, конечно, самое главное, это возможность экспорта в XCode.

Обзор

Среда ориентирована на Python 2.7. Но есть и некоторые фишки из 3-й ветки. Например, сработает и такой код:

print "Hello, world"

и код

print ("Hello, world")

Кроме стандартных библиотек, есть несколько библиотек для непосредственной разработки для iOS. Остановлюсь на одной. Она называется ui и отвечает за GUI.

Рассмотрим несколько примеров работы с этой библиотекой. Очень интересно, что в Pythonista графический интерфейс можно задавать программно, а можно нативно:

import ui

def button_tapped(sender):
    sender.title = 'Hello'

view = ui.View()                                      # [1]
view.name = 'Demo'                                    # [2]
view.background_color = 'white'                       # [3]
button = ui.Button(title='Tap me!')                   # [4]
button.center = (view.width * 0.5, view.height * 0.5) # [5]
button.action = button_tapped                         # [6]
view.add_subview(button)                              # [7]
view.present('sheet')                                 # [8]

Это первый пример по работе с библиотекой ui. Разберём программу построчно:

1) Сначала создаём объект View;
2) Потом задаём имя этого объекта, оно будет отображаться в его заголовке;
3) Устанавливаем цвет фона объекта — белый, можно задавать словом, а можно при помощи RGB;
4) Создаём кнопку с надписью «Tap me!»;
5) Размещаем кнопку на объекте;
6) Задаём функцию, которая будет выполняться при нажатии на кнопку. (В данном случае изменится надпись на кнопке);
7) Уточняем, что «button» является наследником «view»;
8) Наконец, вызываем метод view.present() для отображения объекта на экране iOS устройства.

Вот что будет происходить на айпаде:

imageimage

Но тоже самое можно сделать и нативно:

1) Создадим скрипт с UI:

image

2) Открыв UI, нажмем на кнопку «+» и выберем button:

image

3) Растянем кнопку и разместим её по центру экрана:

image

4) Откроем атрибуты кнопки и зададим функцию, срабатывающую при её нажатии:

image image

4) Перейдём в редактор скрипта и напишем функцию:

def button_tapped(sender):
    sender.title = 'Hello'

Скажем, к какому UI привязать данный скрипт:

ui.load_view('My UI').present('sheet')

image
5) Запустим программу:

imageimage

В завершение

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

Рекомендую посетить сайт создателей Pythonista. На нём есть документация , к сожалению, только на английском языке.

Автор: Snusmumrick97

Источник

Разработка под iOS, Python, Блог компании Журнал Хакер


Рекомендация: подборка платных и бесплатных курсов Python — https://katalog-kursov.ru/

Часто нам приходится совершать со своим iPhone монотонные и довольно скучные манипуляции, которые заставляют нас с завистью смотреть на десктопы с их безграничными возможностями настройки, скриптинга и автоматизации действий. Да что там десктопы — даже на пользователей Android с их вездесущим Tasker’ом, с помощью которого можно запрограммировать смартфон на что угодно. В iOS существование подобных приложений невозможно, но у нас есть небольшая лазейка.

В этой статье я хочу рассказать о Pythonista — среде разработки на языке Python (версии 2.7.5) для iOS, которая позволяет в том числе писать полноценные приложения с графическим интерфейсом. Однако мы будем использовать ее для несколько иных целей — для создания простых подсобных скриптов, которые будут автоматизировать рутинные операции.

Pythonista включает в себя множество предустановленных библиотек, в том числе те, что помогут нам получить доступ к функциональности iOS. Как пример можно привести clipboard, позволяющий читать и писать в буфер обмена, contacts для работы с адресной книгой, keychain, location и другие.

Кроме встроенных, нам также понадобятся сторонние Python-модули. Для Pythonista существует два аналога всем известного pip. Это pipista 2.0 и Pypi. Чтобы установить пакет с помощью первого, необходимо сохранить скрипт в корневой каталог и выполнить такую команду:

import pipista
pipista.pypi_install('Name_of_library')

У этой библиотечки есть также функции pypi_download(), pypi_search() и pypi_versions(), что позволяет считать ее полноценной заменой pip. Второй установщик требует более четких запросов. Например, необходимо указать версию пакета — это удобно, если по какой-то причине не хочешь использовать последнюю версию.

from Pypi import Installer
Installer('Name_of_library', 'Version').install()

У этого установщика также есть дополнительные функции.

Как запустить скрипт с главного экрана

Для этого есть две возможности: *Pythonista Shortcut* и *Launch Center Pro*. В первом случае все просто: достаточно зайти с девайса на сайт, ввести имя скрипта и аргументы, нажать на кнопку Create Shortcut, затем сохранить эту страницу на рабочий стол, используя стандартные функции Safari.

Вторая программа куда интересней. Чтобы запустить скрипт из нее, необходимо создать событие и в поле *URL* прописать вот такую строчку: «pythonista://script_name?action=run&args=», где script_name — имя скрипта с учетом иерархии каталогов, а после args= необходимо перечислить аргументы (если они есть). Также присутствует возможность запуска по времени или с определенной регулярностью.

Есть и возможность упаковать скрипт в полноценное iOS-приложение. Для этого достаточно скачать [архив](goo.gl/jsQK0b) с проектом XCode с официального сайта и заменить стандартный скрипт с Hello, world на свой. После этого можно собрать этот проект в XCode и запустить на симуляторе, а если есть аккаунт разработчика Apple, то и на гаджете.

INFO

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

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

Скрипты

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

Быстрая отправка твита

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

import tweepy
import clipboard

# Ключи Twitter-приложения
consumer_key = "----------"
consumer_secret = "----------"
access_key="----------"
access_secret="----------"

# Представляемся системе
auth = tweepy.OAuthHandler(consumer_key, consumer_secret)
auth.set_access_token(access_key, access_secret)
api=tweepy.API(auth)

# Публикуем твит
text = clipboard.get()
if len(text)<=140 and len(text)>0:
    api.update_status(text)

Скрипт подключается к аккаунту, используя имеющиеся ключи. Их можно получить на официальном сайте Twitter. Чтобы получить все ключи, нужно создать приложение, затем перейти на вкладку Keys and Access Tokens и нажать на кнопку Create my access token. Таким образом мы получим четыре необходимых нам ключа. Чтобы скрипт смог постить сообщения, необходимо дать приложению такие права на вкладке Permissions.

Во всем остальном функциональность крайне проста. Скрипт берет строку из буфера обмена, проверяет, соответствует ли строка формату твита (не более 140 символов), и постит ее.

Быстрое сохранение в Instapaper

Теперь о не менее популярном сервисе Instapaper, позволяющем сохранять страницы для офлайн-чтения. Следующий трехстрочный скрипт добавляет страницу из буфера обмена прямо в установленный на девайсе клиент сервиса.

import webbrowser, clipboard
addnew='x-callback-instapaper://x-callback-url/add?url='+clipboard.get()
webbrowser.open(addnew)

Cкрипт использует так называемые x-callback-url — мини-API приложений, которые можно вызывать через встроенный браузер. На официальном сайте этой фичи есть список приложений, поддерживающих эту возможность. Структура x-callback-url-запросов такая:

x-callback-Имя_Приложения://x-callback-url/Функция?Параметр=

Генератор паролей

Да, именно генератор паролей. Есть куча приложений со схожей функциональностью, но мы сделаем свой. Просто потому, что хотим :).

import random, string,clipboard
pass = ''
for x in range(random.randrange(8,12)):
    pass += random.choice(string.ascii_letters + string.digits)
clipboard.set(pass)

Данный скрипт поможет создать пароль с высокой устойчивостью к подбору (с включением чисел и букв). Идея алгоритма крайне проста: в пустую строчку добавляется случайное (от 8 до 11) число символов из вышеупомянутого набора. Далее пароль помещается в буфер обмена.

Отправка текущего местоположения на email

Иногда проще нажать на кнопку и отправить собеседнику свой адрес, чем объяснить, где ты.

import smtplib, location, time
from email.mime.text import MIMEText

# SMTP-сервер
server = "адрес_сервера"
user_passwd = "пароль"
port = 22
user_name = "отправитель@мэйл"
send_name='получатель@мэйл'

# Выполняем подключение и регистрацию
s = smtplib.SMTP(server, port)
s.ehlo()
s.starttls()
s.ehlo()
s.login(user_name, user_passwd)

# Получаем координаты
location.start_updates()
time.sleep(10)
location.stop_updates()
loc = location.get_location()
addr = location.reverse_geocode(loc)[0]

# Формируем и отправляем письмо
Text = 'Я нахожусь по адресу: ' + addr['Country'] + ', город ' + addr['City']+', ' + addr['Name']
letter = MIMEText(Text,'html','utf-8')
letter['Subject']= 'Текущая геолокация'
letter['To']=send_name
letter=letter.as_string()
s.sendmail(user_name,send_name,letter)
s.close

Скрипт состоит из двух частей: первая — это работа с почтовым сервером, вторая — получение текущего адреса и отправка письма. Остановимся на второй поподробнее. Дело в том, что функции «получить текущее местоположение» в библиотеке location нет, но есть две функции, позволяющие получить список часто посещаемых мест. Так как создание списка длится всего десять секунд (time.sleep(10)), то в нем будет всего один объект с текущим адресом. Этот объект — словарь. Получим необходимые значения по ключам и занесем красивую фразу в строку Text, которую мы потом и отправим.

Отправка фотографии на сервер по FTP

Уже известная нам библиотека clipboard позволяет работать не только с текстом, но и с изображениями. Это открывает нам новые возможности. Как насчет скрипта, который позволяет сохранить фотографию из буфера обмена на FTP-сервер?

import ftplib, clipboard

# Получаем изображение и сохраняем в виде файла
a=clipboard.get_image()
filename='out.jpg'
a.save(filename)

# Подключаемся к серверу и заливаем картинку
con=ftplib.FTP('Host','Login','Password')
f=open(filename,'rb')
send=con.storbinary(filename,f)
con.close()

Скрипт можно немного изменить, написав в первых двух строчках

import ftplib, photos
a=photos.get_image()

Тогда на сервер отправится не скопированная, а последняя отснятая фотография. А если заменить первые две строчки на эти:

import ftplib, photos
a=photos.capture_image()

то iOS предложит сделать фотографию.

Работа с удаленным сервером по SSH

У многих из нас есть удаленные серверы. У кого-то это домашний медиапроигрыватель или файлопомойка, другие рулят серверами на Amazon. Как управлять ими с iPhone или iPad? Можно скачать какой-нибудь FTP-клиент, но это не вариант, если необходимо регулярно выполнять одинаковые задачи, например делать бэкап. Стивен Миллард (Stephen Millard) написал [скрипт](goo.gl/Tt14cC), позволяющий выполнять удаленные команды через SSH. В упрощенном виде (без проверки на правильность введенных данных и вывод логов) он выглядит так:

import paramiko
import console

# Адрес, логин и имя исполняемой команды
strComputer = 'адрес'
strUser = 'логин'
strPwd = 'пароль'
strCommand = 'имя_команды'

# Подключаемся к серверу
client = paramiko.SSHClient()
client.set_missing_host_key_policy(paramiko.AutoAddPolicy())
client.connect(hostname=strComputer, username=strUser, password=strPwd)

# Выполняем команду
stdin, stdout, stderr = client.exec_command(strCommand)
print stdout.read()

client.close()

Для выполнения набора команд достаточно скопировать строчку «stdin, stdout, stderr = client.exec_command(strCommand)» несколько раз с различными командами (либо перечислить все команды через точку с запятой. — Прим. ред.).

Сокращаем ссылки при помощи goo.gl

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

import googl, clipboard

client = googl.Googl("ключ")
result = client.shorten(clipboard.get())
clipboard.set(result['id'])

Cкрипт получает URL из буфера обмена, конвертирует его и помещает обратно в буфер. Перед запуском скрипта необходимо получить API Access Key. Для этого заходим на страницу API, нажимаем Add project и в списке доступных сервисов включаем URL Shortener API. Далее в левом меню выбираем вкладку APIs & auth, подменю Credentials и жмем кнопку Create new Key, далее Browser Key. После получения ключа вставляем его в скрипт.

Обрати внимание, что в ходе исполнения скрипта переменной result присваивается словарь вида {‘kind’: ‘urlshortener#url’, ‘id’: ShortLink’, u’longUrl’: ‘LongLink’}. Так как нам необходима только короткая ссылка, в буфер обмена заносится значение по ключу ‘id’.

Очистка записной книжки

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

import contacts
a = contacts.get_all_people()
for i in a:
    contacts.remove_person(i)
contacts.save()

Просто пробегаемся по списку контактов. Главное — не забыть сохранить сделанные изменения (последняя строка).

Импорт друзей из ВК в записную книжку

Наконец, самый сложный и длинный скрипт — импорт номеров телефонов из «ВКонтакте» в записную книжку. Как и у всех остальных, у «ВКонтакте» есть API. Для питона существует несколько библиотек для работы с ним. Самая известная и самая простая в использовании — библиотека со скромным именем vk.

import vk, datetime, contacts

# Функция для конвертации даты из формата ВК в формат iOS
def convertdate(date):
    date = date.split('.')
    if len(date) == 2:
    return datetime.datetime.combine(datetime.date(1604,int(date[1]),int(date[0])),datetime.time(0, 0))
    else:
    return datetime.datetime.combine(datetime.date(int(date[2]),int(date[1]),int(date[0])),datetime.time(0, 0))

# Подключаемся к ВК и получаем список друзей
vkapi = vk.API('ID-приложения', 'логин', 'пароль')
a = vkapi.friends.get(fields='contacts,bdate')
a = a['items']

# Проходим по списку полученных контактов и импортируем их по одному
for i in a:
    Temp = contacts.Person()
    Temp.last_name= i['last_name']
    Temp.first_name = i['first_name']
    if 'mobile_phone' in i.keys():
    try:
        Temp.phone=[('mobile',i['mobile_phone'])]
    except:
        pass
    if 'home_phone' in i.keys():
    try:
        Temp.phone.append(('home',i['home_phone']))
    except:
        pass
    Temp.url = [('vk','http://vk.com/id'+str(i['id']))]
    if 'bdate' in i.keys():
    Temp.birthday = convertdate(i['bdate'])
    contacts.add_person(Temp)

# Сохраняем контакты
contacts.save()

Как и в случае с твиттером, для скрипта необходимо создать «приложение» внутри «ВКонтакте». Чтобы сделать это, перейди на вкладку «Приложения» на сайте VK, потом на вкладку «Управление» и нажми кнопку «Создать приложение». На странице приложения перейди на вкладку «Настройки» и скопируй «ID Приложения». Вставь «ID Приложения», «Логин» и «Пароль» в скрипт.

Разберемся, как работает этот скрипт. Сначала мы получаем список друзей. По умолчанию функция friends.get() возвращает словарь, состоящий из двух полей: count и items. Нас, несомненно, интересует второе, но так как мы хотим получить не только имена и фамилии, то передадим функции параметр fields, указывающий на то, что мы хотим узнать. Далее мы идем по списку словарей, где каждый словарь — это пользователь. При каждой итерации мы создаем переменную Temp типа Person и по очереди добавляем в нее поля.

В процессе прохода по контактам скрипт решает несколько проблем. Первая проблема возникает при экспорте телефонных номеров, ведь очень часто мы встречаем в ВК номера типа «кому надо — знают», «секрет» и подобные. Чтобы скрипт смог обработать подобные записи, не падая, используется оператор try. Вторая проблема возникла с несовпадением формата даты рождения. В полученном из ВК словаре она записана в виде строки формата DD.MM.YYYY, а в поле birthday необходимо заносить данные в формате datetime.datetime. Для этого и нужна функция convertdate в начале скрипта. Кроме того, дата рождения может быть не указана вовсе.

Встроенные библиотеки Pythonista

  • canvas — библиотека векторной графики;
  • clipboard — работа с буфером обмена;
  • console — функции, связанные с вводом и выводом текста;
  • contacts — доступ к записной книжке;
  • editor — работа с текстовым редактором Pythonista;
  • keychain — доступ к API Keychain;
  • linguistictagger — лингвистический анализ;
  • location — геолокационные сервисы;
  • motion — снятие показаний сенсора;
  • notification — работа с уведомлениями;
  • photos — работа с сохраненными фотографиями;
  • scene — 2D-графика и анимация;
  • sound — библиотека звуков;
  • speech — конвертация текста в речь;
  • ui — нативный GUI для iOS.

Заключение

Несмотря на большое число примеров, мы рассмотрели далеко не все возможности Pythonista. А ведь ее функционала хватает на очень многое. Например, в App Store уже выложено несколько приложений, созданных в этой программе. К тому же в скором времени создатель Pythonista обещает выпустить обновление с поддержкой iPhone 6 и 6+ и двумя новыми модулями для работы с напоминаниями и периферийными Bluetooth-устройствами.

WWW

Официальный форум Pythonista: omz-forums.appspot.com/pythonista
Документация по встроенным модулям: omz-software.com/pythonista/docs/ios
Большая статья о возможностях Pythonista: www.macstories.net/stories/automating-ios-how-pythonista-changed-my-workflow
Сборник Pythonista-скриптов: github.com/Pythonista-Tools/Pythonista-Tools

image

Впервые опубликовано в журнале «Хакер» от 02/2015.
Автор: Виктор Паперно (Snusmumrick97)

Подпишись на «Хакер»

  • Бумажный вариант
  • «Хакер» на iOS/iPad
  • «Хакер» на Android

Мобильная веб-разработка на Python становится все более популярной. И хотя Python изначально не создавался для создания ПО для смартфонов и планшетов, благодаря Kivy это стало возможным. Сегодня мы продолжаем рассматривать особенности использования этого фреймворка. В частности, поговорим о том, что такое язык дизайна  KV, как создавать приложение Kivy, генерировать установочный apk-пакет, как создавать программу для iOS, используя Python.

Содержание

  1. Использование языка дизайна KV
  2. Как создать приложение Kivy?
  3. Как создать apk-файл?
  4. Как создать приложение для iOS

Использование языка дизайна KV

В поставку Kivy входит язык KV, с помощью которого создается дизайн приложений. С помощью этого языка можно отдельно работать с дизайном, не затрагивая логику приложения. В него входит поддержка принципа разделения ответственности, и Kivy является частью архитектурного паттерна «Модель-Представление-Контроллер). 

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

from kivy.app import App

from kivy.uix.button import Button

 

class ButtonApp(App):

    def build(self):

        return Button()

 

    def on_press_button(self):

        print('Вы нажали на кнопку!')

 

if __name__ == '__main__':

    app = ButtonApp()

    app.run()

Первоначально такой синтаксис может показаться странным, поскольку создание кнопки осуществляется без каких-либо атрибутов. Также к ней не привязываются никакие события. Здесь Kivy пытается найти файл, имеющий такое же имя, как и у класса, только строчными буквами и без части App в названии. 

В этом примере в качестве имени класса выступает ButtonApp. Следовательно, Kivy будет искать button.kv. Если такой файл есть в наличии, а его форматирование было выполнено правильно, то Kivy его будет использовать при загрузке UI. 

Давайте попробуем создать такой файл и добавить следующий код: 

<Button>:

    text: 'Press me'

    size_hint: (.5, .5)

    pos_hint: {'center_x': .5, 'center_y': .5}

    on_press: app.on_press_button()

Что делает каждая из этих строк?

  • Выполняет действия, аналогичные вызову Button в коде приложения на Python. Задача – осмотреть инициализированный объект для определения кнопки.
  1. Устанавливает значение text для кнопки. 
  2. Устанавливает ширину и высоту кнопки. Для этого используется size_hint.
  3. Используя pos_hint устанавливает позицию кнопки.
  4. Устанавливает событие при нажатии on_press. Чтобы передать Kivy место обработчика событий, необходимо использовать app.on_press_button(). Здесь Kivy будет осуществлять поиск соответствующего метода в классе Application.

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

И это далеко не все, что он умеет. Более подробную информацию можно получить в официальной документации Kivy.

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

Как создать приложение Kivy?

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

  1. Сложение.
  2. Вычитание.
  3. Умножение.
  4. Деление.

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

В результате, калькулятор должен выглядеть так:Kivy - Создание мобильных приложений на Python (Часть 2)

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

from kivy.app import App

from kivy.uix.boxlayout import BoxLayout

from kivy.uix.button import Button

from kivy.uix.textinput import TextInput




class MainApp(App):

    def build(self):

        self.operators = ["/", "*", "+", "-"]

        self.last_was_operator = None

        self.last_button = None

        main_layout = BoxLayout(orientation="vertical")

        self.solution = TextInput(

            multiline=False, readonly=True, halign="right", font_size=55

        )

        main_layout.add_widget(self.solution)

        buttons = [

            ["7", "8", "9", "/"],

            ["4", "5", "6", "*"],

            ["1", "2", "3", "-"],

            [".", "0", "C", "+"],

        ]

        for row in buttons:

            h_layout = BoxLayout()

            for label in row:

                button = Button(

                    text=label,

                    pos_hint={"center_x": 0.5, "center_y": 0.5},

                )

                button.bind(on_press=self.on_button_press)

                h_layout.add_widget(button)

            main_layout.add_widget(h_layout)




        equals_button = Button(

            text="=", pos_hint={"center_x": 0.5, "center_y": 0.5}

        )

        equals_button.bind(on_press=self.on_solution)

        main_layout.add_widget(equals_button)




        return main_layout

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

  1. Строки 8-10. Здесь создается список operators, а также ряд других значений, которые будут использоваться далее. Это такие значения, как last_was_operator и last_button.
  2. Строки 11-15. Мы создаем main_layout, который будет лейаутом верхнего уровня. К нему будет присоединен виджет только для чтения TextInput.
  3. Строки 16-21. Из списков, хранящих большинство кнопок приложения, создается большой вложенный список. 
  4. Строка 22. Здесь мы инициализируем начало цикла for для кнопок. Выполняются такие действия для каждого из вложенных списков:
    1. Строка 23. Создается горизонтально ориентированный BoxLayout.
    2. Строка 24. Здесь инициализируется начало еще одного цикла for для объектов, входящих во вложенный список. 
    3. Строки 25-39. Добавляются кнопки и обработчики событий к ним. Затем они добавляются в качестве части горизонтального BoxLayout из строки 23.
    4. Строка 31. Здесь мы добавляем наш лейаут к main_layout.
  5. Строки 33-37. Здесь создается кнопка равно (=) и привязывается к обработчику событий. Затем она добавляется к main_layout.

После выполнения всех этих действий создается обработчик .on_button_press(). Код будет таким. 

def on_button_press(self, instance):

    current = self.solution.text

    button_text = instance.text




    if button_text == "C":

        # Очистка виджета с решением

        self.solution.text = ""

    else:

        if current and (

            self.last_was_operator and button_text in self.operators):

            # Не добавляйте два оператора подряд, рядом друг с другом

            return

        elif current == "" and button_text in self.operators:

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

            return

        else:

            new_text = current + button_text

            self.solution.text = new_text

    self.last_button = button_text

    self.last_was_operator = self.last_button in self.operators

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

И, наконец, мы добавляем функцию .on_solution()

def on_solution(self, instance):

    text = self.solution.text

    if text:

        solution = str(eval(self.solution.text))

        self.solution.text = solution

Здесь функция получает текстовые данные из solution, после чего задействуется функция eval() для вычислений. Если пользователем создается формула типа 1+2, то eval возвращает результат. В конце результат устанавливается в качестве нового значения виджета solution.

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

После того, как мы запустим приведенный выше код, появится такое окно с приложением.Kivy - Создание мобильных приложений на Python (Часть 2)

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

Как создать apk-файл?

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

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

$ pip install buildozer

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

$ buildozer init

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

[app]

 

# (str) Название вашего приложения

title = KvCalc

 

# (str) Название упаковки

package.name = kvcalc

 

# (str) Домен упаковки (нужен для упаковки android/ios)

package.domain = org.kvcalc

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

Выполните команду.

$ buildozer -v android debug

Через 15-20 минут будет создан файл, который переносим в смартфон и запускаем. После установки программы запускаем ее и получаем следующий результат.Kivy - Создание мобильных приложений на Python (Часть 2)

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

Чтобы собрать приложение для iOS, необходимо воспользоваться компьютером под управлением OS X: MacBook, iMac. 

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

$ brew install autoconf automake libtool pkg-config

$ brew link libtool

$ sudo easy_install pip

$ sudo pip install Cython==0.29.10

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

$ git clone git://github.com/kivy/kivy-ios

$ cd kivy-ios

$ ./toolchain.py build python3 kivy

Если вам отображается ошибка, где говорится, что iphonesimulator не удалось найти, тогда попробуйте найти решение проблемы на StackOverflow

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

Shell

$ cd /Applications/Python 3.7/

$ ./Install Certificates.command

Теперь вернитесь назад и запустите команду повторно. 

После того, как эти команды будут выполнены, можно создать проект Xcode с использованием скрипта toolchain. Переименуйте приложение в main.py, а потом выполните следующую команду.

./toolchain.py create <title> <app_directory>

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

Оцените качество статьи. Нам важно ваше мнение:

Понравилась статья? Поделить с друзьями:
  • Как написать приложение для android на unity
  • Как написать приложение для android на delphi
  • Как написать приложение для android для чайников
  • Как написать прикрыть рогожей
  • Как написать прикольное сообщение мужчине