Урок 3. Кортежи. Словари.

Основы Python и Django. -> Bash и виртуальное окружение Python

Bash и виртуальное окружение Python.

Интерпретатор BASH помогает автоматизировать многие рутинные действия.

Например активирование виртуального окружения.

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

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

Создадим bash скрипт auto.sh с командой активации виртуального окружения.

source ./venv/bin/activate

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

Добавим право на исполнение.

chmod +x auto.sh

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

Сделаем это в файле .bashrc

cd () {
    builtin cd ${1:+"$@"} 
    if [ -f "auto.sh" ]
    then
     . ./auto.sh
    fi  
}

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

builtin cd ${1:+"$@"}

Затем проверяем существование файла и если он есть запускаем его.

    if [ -f "env.sh" ]
    then
     . ./auto.sh
    fi

Словари.

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

Доступ к значениям элементов словаря по ключу.

#!/usr/bin/python

dict = {'Name': 'Zara', 'Age': 7, 'Class': 'First'}

print dict['Name']

Ключ может быть числом.

dict = {1: 'one', 2: 'two'}
print dict[1]
print dict[3]

Traceback (most recent call last):
  File "dict_ex.py", line 3, in <module>
    print dict[3]
KeyError: 3

Безопасное извлечение.

print dict.get(3,'no')

Изменение словаря

dict = {'Name': 'Zara', 'Age': 7, 'Class': 'First'}

dict['Age'] = 8; # update existing entry
dict['School'] = "DPS School"; # Add new entry

Удаление элементов из словаря.

dict = {'Name': 'Zara', 'Age': 7, 'Class': 'First'}

del dict['Name']; # remove entry with key 'Name'
dict.clear();     # remove all entries in dict
del dict ;        # delete entire dictionary

Ключ должен быть неизменяемым объектом.

dict = {['Name']: 'Zara', 'Age': 7}


Traceback (most recent call last):
   File "test.py", line 3, in <module>
      dict = {['Name']: 'Zara', 'Age': 7};
TypeError: list objects are unhashable

Встроенные функции работы со словарем.

Создание словаря.

md = dict(name='Vova', age=23)

print(md)

Длинна словаря

len(dict)

Строковое представление.

str(dict)
type(variable)

Создание словаря из 2 списков функцией zip.

d1 = ['one', 'two', 'three']
d2 = [1, 2, 3]
d3 = dict(zip(d1,d2))
print(d3

>> {'three': 3, 'two': 2, 'one': 1}

Встроенные методы словарей.

dict.clear() # очистить
dict.copy() # склонировать (сделать копию)




dict.fromkeys(seq[, value])

Create a new dictionary with keys from seq and values set to value.

seq = ('name', 'age', 'sex')
val = (10,20,30)
dict = dict.fromkeys(seq,val)
print dict
>> {'age': (10, 20, 30), 'name': (10, 20, 30), 'sex': (10, 20, 30)}

dict.get(key, default=None)

Проверка на существование ключа.

dict.has_key(key)  # only for Python 2!

if 'key' in md:
    print('Yes')
else:
    print('No')

Получение всех ключей словаря.

print(dict.keys())

>> dict_items([('two', [1, 2, 3]), ('one', [1, 2, 3]), ('three', [1, 2, 3])]) # python 3
>> [('three', [1, 2, 3]), ('two', [1, 2, 3]), ('one', [1, 2, 3])] # python 2

Получение всех значений словаря.

print(dict.values())
>> dict_values([[1, 2, 3], [1, 2, 3], [1, 2, 3]]) # python 3
>> [[1, 2, 3], [1, 2, 3], [1, 2, 3]] # python 2

Получение всех ключей-значений словаря.

print(dict.items())

>> dict_items([('two', [1, 2, 3]), ('one', [1, 2, 3]), ('three', [1, 2, 3])]) # python 3
>> [('three', [1, 2, 3]), ('two', [1, 2, 3]), ('one', [1, 2, 3])] # python 2

Обход словаря в цикле.

for key, value in d.iteritems(): # For Python 2.x

for key, value in d.items(): $ for Python 3.x

Альтернативный способ обхода по ключам dict.keys().

for key in d3.keys():
    print(d3[key])

Массовое обновление словаря словарем.

dict.update(dict2)

Функция НЕ возвращает а изменяет словарь.

Преобразование словаря в строку json.

import json

json.dumps({"one": 1, "two": '2'})

Запишем в файл.

# write into file
f = open('tst.txt','w+')
f.write(s1)
f.close()

Для записи строки ее нужно преобразовывать из объекта словаря в строку функцией dumps.

Считаем из файла.

# read from file
f = open('tst.txt','r')
st = f.read()
f.close()
st_dict = json.loads(st)
print(st_dict['two'])

Для работы со словарем его необходимо преобразовывать из строки в объект ф-цией loads.

Основы Python и Django. -> Библиотека requests.

Библиотека requests.

дока

Установка.

pip install requests

Использование.

import requests

Запрос с передачей хэдеров.

r=requests.get(url, headers={"key":"val"})
print(t.text)

POST запрос

url = 'https://webmonstr.com/ru/login/'
data = {"username": "test", "password": "test"}
r = requests.post(url,data=data)
print(r.text)
Основы Python и Django. -> Библиотека beautifulsoup.

Библиотека BeatifulSoup.

Установка.

pip install bs4

пример html документа

html_document = '''    
<html>
    <head>
        <title>Главная страница</title>
    </head>
    <body>
        <h1> Заголовок H1  </h1>
        <a href="http://google.com"> Ссылка 1 </a>
        <a href="http://yandex.ru"> Ссылка 2 </a>
        <div id="block_id">
            Блочный элемент
        </div>
        <p class="p_class"> Параграф 1 </p>
        <p class="p_class"> Параграф 2 </p>
        <p class="p_class"> Параграф 3 </p>
        <table>
            <tr> 
                <td valign="top"> Ячейка 1 </td>
                <td valign="top"> Ячейка 1 </td>
                <td valign="top"> Ячейка 3 </td>    
            </tr>
            <tr> 
                <td valign="top"> Ячейка 1 </td>
                <td valign="top"> Ячейка 1 </td>
                <td valign="top"> Ячейка 3 </td>    
            </tr>
        </table>
    </body>
</html>    
'''

Чтение DOM.

from bs4 import BeautifulSoup
soup = BeautifulSoup(html_doc, 'html.parser')

Заголовок документа.

soup.title.string

Поиск одного и группы элементов.

el = soup.find('h1')

Найдем все ссылки на странице.

soup.findAll('a')

Доступ к тексту и атрибутам тега.

link.get('href')
link.text

Проход по массиву

for link in soup.findAll('a'):
    print(link.get('href'))

Поиск одного элемента по id.

el = soup.find('h1',{'id': 'my-header'})

Поиск многих элементов по имени класса.

els = soup.findAll('div',{'class': 'class_name'})

по нескольким классам

show = soup.find('div', class_='action-link showPhonesLink')
show = soup.find('div', attrs={'class': 'action-link showPhonesLink'})

Поиск по css атрибутам.

els = soup.findAll('div',attrs={'id': '123'})

Метод select

results = soup.select('td[valign="top"]')
  • возвращает массив
Основы Python и Django. -> Виртуальное окружение. Установщик PIP.

Установщик pip. Виртуальное окружение.

При разработке программ на Python часто возникает необходимость в установке сторонних библиотек (пакетов) , не входящих в поставку Python.

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

Установить пакет python можно вручную, распаковав архив в нужное место.

Первым делом Python пытается найти импортируемую библиотеку в текущем каталоге.

Это можно проверить, создав файл библиотеки mylib.py.

print('Importing mylib')

И в другом файле попытаться его импортировать.

import mylib

Вывод.

shell>python imp.py 
Importing mymodule
shell>

Если файл положить в каталог lib например, то импорт будет следующим:

import lib.mylib

При этом необходимо не забыть создать в каталоге специальный файл init.py который обозначит этот каталог как пакет и сделает возможным импорт из него.

Установщик pip облегчает задачу установки пакетов.

Он оперирует репозиторием пакетов на сайте https://pypi.org и тянет их от туда.

Установить его в систему можно командой.

apt install python-pip

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

pip install package_name1 package_name2

Мы можем создать список всех необходимых библиотек в файле requirements.txt (например) перечислив их в столбик.

packege_name1
package_name2

И потом воспользоваться ключем -r для передачи файла-списка в установщик pip.

pip install -r requirements.txt

Где еще Python ищет библиотеки при импорте?

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

Этот модуль взаимодействует напрямую с интерпретатором Python.

import sys
print(sys.path)

Можно запустить одной командой прямо из bash консоли.

python -c "import sys; print('\n'.join(sys.path))"

Вывод

/usr/lib/python2.7
/usr/lib/python2.7/plat-x86_64-linux-gnu
/usr/lib/python2.7/lib-tk
/usr/lib/python2.7/lib-old
/usr/lib/python2.7/lib-dynload
/home/zdimon/.local/lib/python2.7/site-packages
/usr/local/lib/python2.7/dist-packages
/usr/lib/python2.7/dist-packages
/usr/lib/python2.7/dist-packages/PILcompat
/usr/lib/python2.7/dist-packages/gtk-2.0
/usr/lib/python2.7/dist-packages/ubuntu-sso-client
/usr/lib/python2.7/dist-packages/wx-3.0-gtk2

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

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

pip install markdown

Вы получите ошибку прав доступа так как текущий пользователь не может писать в /usr/local/lib/python2.7/dist-packages.

ERROR: Could not install packages due to an EnvironmentError: 
[Errno 13] Permission denied: '/usr/local/lib/python2.7/dist-packages/markdown

Выход из этой ситуации - это изменить переменную окружения интерпретатора sys.path, указав в нем путь нашего проекта вместо системных путей.

Это обеспечивает такая программа как virtualenv.

Установка

apt install virtualenv

Создание виртуального окружения.

virtualenv venv # python 2

virtualenv -p python3 venv  # python 3

При этом venv - произвольное имя папки, которая создается в текущей директории.

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

После создания этой директории необходимо запустить bash скрипт activate из каталога venv/bin.

Именно он и будет изменять пути в sys.path к нашим зависимостям.

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

Это каталог venv/lib/python3.5/site-packages/.

Основы Python и Django. -> Домашнее задание. Игра "очко".

Домашнее задание

#! /usr/bin/env python
# -*- coding: utf-8 -*-

questions = [ 
        {
            "question": "Оператор вывода на экран?", 
            "answers": [
                {"text": "1 echo", "is_true": False},
                {"text": "2 print", "is_true": True},
                {"text": "3 output", "is_true": False}
            ] 
        },

        {
            "question": "Оператор цикла?", 
            "answers": [
                {"text": "1 for", "is_true": True},
                {"text": "2 if", "is_true": False},
                {"text": "3 loop", "is_true": False}
            ]
        },

    ]

for i in questions:
    print("\x1b[34;47m" + i["question"] + "\x1b[0m")
    for j in i["answers"]:
        print("\x1b[34;47m" + j["text"] + "\x1b[0m")

    value = input("Укажите правильный номер: ")
    value = int(value)
    print("---------------------")
    if i["answers"][value - 1]["is_true"] == True:
        print('\x1b[30;42m' + 'Верно!' + '\x1b[0m')
    else:
        print('\x1b[30;41m' + 'Не верно!' + '\x1b[0m')
    print("---------------------")

Написать игру в “очко”.

Суть игры.

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

koloda = [6,7,8,9,10,2,3,4,11] * 4

import random
random.shuffle(koloda)

print('Поиграем в очко?')
count = 0

while True:
    choice = input('Будете брать карту? y/n\n')
    if choice == 'y':
        current = koloda.pop()
        print('Вам попалась карта достоинством %d' %current)
        count += current
        if count > 21:
            print('Извините, но вы проиграли')
            break
        elif count == 21:
            print('Поздравляю, вы набрали 21!')
            break
        else:
            print('У вас %d очков.' %count)
    elif choice == 'n':
        print('У вас %d очков и вы закончили игру.' %count)
        break

print('До новых встреч!')