Автор: Andrew Svetlov
Архив рубрики: Python
Fabric: Операции
fabric.operations.get(remote_path, local_path = None)
- host: Значение env.host_string, например, myhostname или user@myhostname-222 (двоеточие между именем узла и номером порта заменено на тире для увеличения совместимости с разными ФС)
- dirname: Часть каталога из удалённого пути, т.е. src/projectname в /src/projectname/utils.py
- basename: Часть файла из удалённого пути, т.е. utils.py в /src/projectname/utils.py
- path: Полный удалённый путь: /src/projectname/utils.py
- ПримечаниеЕсли remote_path — абсолютный путь, то только подкаталоги будут созданы локально и переданы в переменные выше. Так, например, get('/var/log', '%(path)s') будет записывать файлы как apache2/access.log,postgresql/8.4/postgresql.log и т.д. в локальный рабочий каталог. Он не будет записывать файлы как var/log/apache2/access.log.Кроме того, когда скачивается один файл, %(dirname)s и %(path)s не имеют особого смысла и будут, соответственно иметь пустое значение и значение, равное %(basename)s. Таким образом, вызов вроде get('/var/log/apache2/access.log', '%(path)s') сохранит локальный файл под именем access.log, а не var/log/apache2/access.log.Такое поведение предназначено для соответствия программе командной строки scp.Если значение не задано, то local_path получает значение "%(host)s/%(path)s" чтобы это было безопасно для использования на нескольких узлах.ПредупреждениеЕсли ваш аргумент local_path не содержит %(host)s и ваш вызов get запускается на нескольких хостах, ваши локальные файлы будут перезаписаны при каждом удачном запуске!Если local_path не использует вышеозначенные переменные (т.е. это просто явный путь) он будет действовать похоже командам scp или cp, перезаписывая при необходимости существующие файлы, скачивая их в нужное место (т.е. get('/path/to/remote_file.txt', 'local_directory') создаст local_directory/remote_file.txt) и т.п.local_path может быть и файлоподобным объектом, например, результатом open('path', 'w') или экземпляром StringIO.ПримечаниеПопытка выполнить get каталога в файлоподобный объект некорректна и вернёт ошибку.ПримечаниеЭта функция будет использовать seek и tell для перезаписи всего содержимого файлоподобного объекта, чтобы это соответствовало поведению put (который тоже использует весь файл). Однако, в отличие от put, указатель файла не будет восстановлен в предыдущую локацию, так как это достаточно бессмыслен
но и/или даже не возможно.ПримечаниеИз-за того, как работают наши слои SSH, временные файлы всё равно будут записаны во временный файл на диске, даже если Вы передаёте в качестве аргумента local_path файлоподобный объект или StringIO. Временные файлы будут удалены, но имейте это в виду и не ожидайте прямой передачи данных в память. (Мы надеемся исправить это в будущем, чтобы дать возможность прямой передачи данных в память.)ПримечаниеЕсли файлоподбный объект, такой как StringIO имеет атрибут name, он будет использован в выводе Fabric, вместо простогоobj> Изменения в версии 1.0: Теперь есть отдельный удалённый рабочий каталог, с которым работает cd, и локальный рабочий каталог, с которым работает lcd.Изменения в версии 1.0: Теперь можно использовать файлоподобные объекты в качестве аргумента local_path.Изменения в версии 1.0: local_path может теперь содержать переменные genb и узла.Изменения в версии 1.0: В аргументе remote_path можно использовать каталоги, которые будут рекурсивно загружены.Изменения в версии 1.0: Возвращает итерируемый объект, содержащий локальные пути, содержащий атрибуты .failed и.succeeded.Изменения в версии 1.5: Использует атрибут name файлоподобного объекта для вывода лога
- fabric.operations.local(command, capture=False, shell=None)
- Выполняет команду на локальной системе.local — это лишь оболочка вокруг использования встроенного модуля Python subprocess с shell=True. Если Вам надо сделать что-то особое — используйте модуль subprocess напрямую.shell передаётся напрямую в аргумент execute subprocess.Popen‘а (что определяет используемую локально оболочку.) В соответствии со документацией, на Unix по умолчанию используется /bin/sh, так что эта опция полезна для установки других значений, например, /bin/bash.local на данный момент не способен одновременно вводить и выводить информация, в отличие от run/sudo. Именованный аргумент capture позволяет переключаться между выводом и вводом при необходимости, значение по умолчанию — False.Когда capture=False, локальные ввод и вывод subprocess’a направляется напрямую на ваш терминал, хотя Вы можете использовать глобальные настройки вывода output.stdout и output.stderr, чтобы спрятать один из них или оба. В этом режиме возвращаемые значения stdout/stderr всегда будут пустыми.Если capture=True, то Вы не увидите никакого вывода на вашем терминале, но возвращаемое значение будет храниться в stdout/stderr.В любом случае, как и при запуске run и sudo, возвращаемое значение содержит атрибуты return_code, stderr, failed и succeeded. Более подробно это описано в run.local будет учитывать менеджер контекста lcd, позволяющий Вам контролировать текущий рабочий каталог вне зависимости от удалённого каталога (которым управляет cd).Изменения в версии 1.0: Добавлены атрибуты succeeded и stderr.Изменения в версии 1.0: Значение по умолчанию для capture изменено с True на False.
- fabric.operations.open_shell(command=None)
- Вызывает интерактивную оболочку на удалённой системе.Если передан аргумент command, то он будет передан по каналу перед тем, как передать управление пользователю.Эта функция чаще всего используется когда Вам нужно взаимодействовать с серьёзными командами оболочки или набором команд, например, при отладке или когда нужно провести полностью интерактивное восстановление при ошибке удалённой программы.Следует иметь ввиду, что интерактивная оболочка в середине скрипта и не является замено
й команды run, которая тоже может взаимодействовать с удалённым хостом (хотя только во время выполнения переданной команды) и подразумевает решение большего количества программных проблем, таких как обработка ошибок и захват ввода/вывода.Конкретнее, open_shell предоставляет больше интерактивности, чем run, использование полноценной удалённой оболочки не позволяет Fabric определить, завершилась ли программа с ошибкой и заполняет ввод/вывод вводом/выводом оболочки, таким как заставки входа, приглашения и т.д.Таким образом, эта функция не имеет возвращаемого значения и не вызывает обработку ошибок Fabric, если какая-либо удалённая программа завершилась с ошибкой.Начиная с версии 1.0.
- fabric.operations.prompt(text, key=None, default='', validate=None)
- Выдаёт пользователю запрос с текстом text и возвращает полученное значение (как raw_input).Для удобства к text будет добавлен одиночный пробел, ничего больше. Таким образом Вы можете завершить свой запрос вопросительным знаком или двоеточием, например prompt("What hostname?").Если указан key, ввод пользователя и будет сохранён как env.
и возвращён этой функцией prompt. Если этот ключ уже существует в env, то его значение будет перезаписано и пользователю будет выдано предупреждение. Если передан параметр default, то он будет выведен в квадратных скобках и будет использоваться в случае, если пользователь ничего не введёт (т.e. нажмёт Enter без ввода текста). По умолчанию значением default является пустая строка. Если значением является не пустая строка, то к нему будет добавлен пробел, так что вызов prompt("Каково имя узла?", default="foo") приведёт к отображению Каково имя узла? [foo] (с пробелом после [foo].)Опциональный именованный аргумент validate может быть вызываемым объектом или строкой:- Если это вызываемый объект, то он будет вызван с полученной от пользователя строкой и должен вернуть значение для сохранения в случае успеха. При ошибке он должен вызвать исключение с сообщением, которое будет показано пользователю.
- Если это строка, то значение, переданное в параметре validate используется как регулярное выражение. Поэтому рекомендуется использовать «сырые» строки. Обратите внимание, что регулярное выражение будет (в любом случае?) требовать полного совпадения.
В любом случае prompt будет перезапрашивать ввод от пользователя до тех пор, пока не пройдёт валидация (или пользователь не нажмёт Ctrl-C).Примечаниеprompt учитывает env.abort_on_prompts и будет вызывать abort вместо запроса, если этот флаг установлен в True. Если Вы хотите заблокировать ввод пользователя безусловно, но в этом случае запросить информацию у пользователя — оберните код при помощи settings.Примеры:
- fabric.operations.put(local_path=None, remote_path=None, use_sudo=False, mirror_local_mode=False, mode=None)
- Загружает один или более файлов на удалённый хост.put возвращает итерируемый объект, содержащий абсолютные пути ко всем загруженным файлам. Этот итерируемый объект содержит также атрибут .failed, содержащий пути к локальным файлам, которые не удалось выгрузить (и потому его можно использовать для логической проверки.) Кроме того, Вы можете использовать .succeeded, который эквивалентен not .failed.local_path может быть как относительным, так и абсолютным путём, или даже каталогом, может содержать символы подстановки оболочки, как они используются в модуле glob. Можно использовать и ~ (так же как в os.path.expanduser).local_path может быть и файлоподобным объектом, как, например, результатом open('path') или экземпляром StringIO.ПримечаниеВ таком случае put постарается прочитать всё содержимое файлоподобного объекта, проматывая его при помощи seek (и будет использовать tell для сохранения предыдущей позиции файла).ПримечаниеИспользование файлоподобного объекта в команде put в аргументе local_path приведёт к удалению временного файла из-за нашей реалиации слоя SSH.remote_path также может быть абсолютным или относительным путём, но применяется к удалённому узлу. Относительный genm трактуется относительно домашней директории удалённого пользователя, но, при необходимости, можно использовать и тильду (т.е. ~/.ssh/).Пустая строка в качестве значения любого из двух аргументов пути будет замещена на текущий рабочий каталог.Хотя протокол SFTP (который используется put) не имеет возможности загрузить файл в локацию, которая не принадлежит подключившемуся пользователю, Вы можете задать use_sudo=True, чтобы обойти это. При использовании этого параметра put загружает файлы во временный каталог на удалённом хосте и затем использует sudo для перемещения их в remote_path.В некоторых случаях желательно чтобы загруженные файлы имели аналогичный режим, как и их локальные «коллеги» (например, когда Вы загружаете выполняемые скрипты). Для этого используйте mirror_local_mode=True.В качестве альтернативы Вы можете использовать именованный аргумент mode для того, чтобы задать режим извлечения так же как и os.chmod или команда Unix chmod.put учитывает результат cd, так что относительные пути в remote_path будут толковаться относительно текущего удалённого рабочего каталога, если это возможно. Таким образом, например, код ниже выгрузит файл в /tmp/files/test.txt а не в ~/files/test.txt:Использование lcd будет влиять на local_path аналогичным образом.Примеры:ПримечаниеЕсли файлоподобный объект, такой как StringIO, имеет атрибут name, то его значение будет использоваться в выводе Fabric, вместо стандартного
obj> Изменения в версии 1.0: Теперь учитывается удалённый рабочий каталог, управляемый cd, и локальный рабочий каталог, управляемый lcd.Изменения в версии 1.0: Теперь можно использовать файлоподобные объекты в аргументе local_path.Изменения в версии 1.0: В аргументе local_path можно задать каталог, который будет рекурсивно выгружен на удалённый узел.Изменения в версии 1.0: Возвращает итерируемый объект, содержащий удалённые пути с атрибутами .failed и.succeeded.Изменения в версии 1.5: Позволяет использовать атрибут name файлоподобного объекта для вывода лога
- fabric.operations.reboot(wait=120)
- Перезагружает удалённую систему.Временно изменяет настройки переподключения (timeout и connection_attempts) чтобы убедиться, что попытки подключения не прекратятся как минимум раньше wait секунд.ПримечаниеПо состоянию на Fabric 1.4, способность переподключиться в пределах сессии больше не требует использования внутреннего API. Хотя мы и не объявляем эту функцию нежелательной, тем не менее добавление к ней новых возможностей не стоит у нас в приоритетах.Пользователи, желающие получить больше возможностей должны посмотреть исходники этой функции (6 хорошо задокументированных строк) и написать свою собственную адаптацию с различными значениями timeout/attempts или дополнительной логикой.Появился в версии 0.9.2.Изменения в версии 1.4: Изменен именованный аргумент wait — ему добавлено значение по умолчанию.
- fabric.operations.require(*keys, **kwargs)
- Проверяет наличие переданных ключей в общем словаре окружения и прерывает выполнение, если их не находит.Позиционными аргументами должны быть строки, определяющие то, какие переменные окружения должны быть проверены. Если какой-либо из этих переменных не существует, Fabric прервёт выполнение и выведен имена отсутствующих ключей.Опциональный именованный аргумент used_for может быть строкой, которая будет отправлена на стандартный вывод, чтобы сообщить пользователю, для каких целей будет использоваться отсутствующая переменная. used_for выводится как часть строки вроде этой:Опциональный именованный аргумент provided_by может быть списком функций или имён функций, или одной функцией или её именем, которые должны быть выполнены для того, чтобы задать эти переменные; он будет включён в сообщение об ошибке.Примечание: Подразумевается, что именованные аргументы применяются ко всем переданным ключам как к группе. Если Вам надо, например, указать для разных ключей разные used_for, Вы должны использовать несколько вызовов require().Изменения в версии 1.1: Позволяет использовать итерируемые значения provided_by, а не одиночные значения.
- fabric.operations.run(command, shell=True, pty=True, combine_stderr=None, quiet=False, warn_only=False, stdout=None,stderr=None)
- Запускает команду оболочки на удалённом узле.Если shell=True (значение gj умолчанию), run выполнит заданную команду через оболочку, которая определяется переменной env.shell (в сумме получается что-то вроде /bin/bash -l -c "
" .) Все двойные кавычки (") или знаки доллара ($) в command будут автоматически экранированы, если shell=True.run возвращает результирующий вывод выполнения удалённой программы в качестве одной (скорее всего состоящей из нескольких строк) строки. Эта строка будет иметь логические атрибуты failed и succeeded, определяющие успешно или нет была выполнена команда, а в атрибуте return_code Вы получите код возврата команды. Более того, он содержит копии запрошенной и реальной строки команды в аргументах .command и .real_command соответственно.Любой текст, введённый в вашем локальном терминале будет перенаправлен в удалённую программу, пока она выполняется; таким образом Вы можете взаимодействовать удалённой программой, вводя пароли и т.п. Более подробно смотрите в разделе Взаимодействие с удалённой программой.Вы можете задать pty=False чтобы не создавать псевдотерминал на удалённом хосте в том случае, если это создаёт проблемы для выполняемой команды. Но, таким образом, Fabric надо будет самому передавать весь ввод удалённой программе, в том числе и пароли. (Если pty=True, удалённый псеводтерминал бдует делать всё это сам.) Подробнее об этом в разделе Псевдотерминалы.Конкретнее, если Вам нужно программно проверить поток вывода ошибок удалённой программы (доступный через атрибут stderr возвращаемого значения функции), Вы можете задать combine_stderr=False. В этом случае есть большая вероятность получения путанного вывода на вашем терминале (хотя возвращаемая run строка будет разделена надлежащим образом). Более подробно смотрите в разделе Комбинирование stdout и stderr.Чтобы игнорировать ненулевой код возвращения задайте warn_only=True. Чтобы и игнорировать ненулевое возвращаемое значение и принудить команду выполняться тихо, задайте quiet=True.Чтобы переопределить какие локальные потоки будут использованы для отображения удалённых stdout и/ил
и stderr, определите stdout или stderr. (По умолчанию используются потоковые объекты Python sys.stdout и sys.stderr.)Например, run("command", stderr=sys.stdout) будет выводить удалённый поток ошибок в локальный поток вывода, сохраняя его как свой собственный атрибут возвращаемого значения (как выше). Или же Вы можете даже передать свой собственный потоковый объект или логировщик, например myout = StringIO(); run("command", stdout=myout).Примеры:Начиная с версии 1.0: Атрибуты succeeded и stderr возвращаемого значения, именованный аргумент combine_stderr, и интерактивное поведение.Изменения в версии 1.0: Значением по умолчанию pty теперь является True.Изменения в версии 1.0.2: Значением по умолчанию combine_stderr теперь является None вместо True. Однако поведение по умолчанFabric: Модель выполнения
Если Вы читали руководство, то Вы должны быть уже знакомы с тем, как Fabric работает (с одной задачей на одном хосте). Однако, во многих ситуациях Вы можете захотеть выполнить несколько задач и/или на нескольких хостах. Возможно, Вы захотите разделить одну большую задачу на несколько маленьких, или обойти список серверов в поисках тех, на которых надо удалить выбранного пользователя. Все эти сценарии требуют некоторых правил о том, как и когда выполняются задачи.Этот документ описывает модель выполнения Fabric, включая главный цикл выполнения, определение списка хостов, создание подключений и т.д.Стратегия выполнения
По умолчанию Fabric работает в одиночном, последовательном режиме выполнения, хотя, начиная с версии 1.3, доступна параллельная модель выполнения (см параллельное выполнение). Поведение по умолчанию заключается в следующем:- Создаётся список задач. На данный момент это просто список аргументов, переданных fab'y, сохраняя порядок аргументов
- Для каждой задачи из разных источников создаётся список хостов (подробнее см «Как создаётся список хостов» ниже)
- Проходится список задач, каждая задача запускается один раз для каждого хоста в списке
- Задачи, для которых нет хостов в списке хостов, выполняются только локально и всегда запускаются только один раз
Таким образом, если у нас есть следующий fabfile:from fabric.api import run, env
env.hosts = ['host1', 'host2']
def taskA():
run('ls')
def taskB():
run('whoami')и мы выполняем команду:$ fab taskA taskB
мы увидим, что Fabric выполнит следующее:- taskA выполняется на host1
- taskA выполняется на host2
- taskB выполняется на host1
- taskB выполняется на host2
Хотя это и упрощённый подход, он позволяет очевидно сопоставить задачи и хосты и (в отличие от инструментов, которые запускают задачу сразу на нескольких узлах) позволяют реализовать логику скрипта, где Вы проверяете результат выполнения предыдущей команды и на основании этого решаете что делать дальше.Определение задач
Подробнее о том, что такое задачи Fabric и с чем их едят, смотрите «Определение задач«Определение списка хостов
Если только Вы не используете Fabric как просто систему запуска локальных скриптов (что возможно, но не является его основной задачей), наличие задач без возможности определить хосты для их выполнения было бы малополезным. Есть несколько способов сделать это, область воздействия этих методов меняется от глобальной до «только на одну задачу» и их можно смешивать в нужных пропорциях.Хосты
Хостами, в данном контексте, называется то, что обычно называется «строками хостов»: строка, которая определяет имя пользователя, имя хоста и номер порта: `username@hostname:port`. Пользователя и порт (и, соответственно, `@` и `:`) могут быть опущены; в таком случае будет использоваться локальное имя пользователя и порт 22. Таким образом, «admin@foo.com:222», «deploy@website» и «nameserver1» могут быть использованы в качестве строк хостов.Так же поддерживается нотация IPv6, например, «::1», «[::1]:1222», «user@2001:db8::1» или «user@[2001:db8::1]:1222». Квадратные скобки нужны только для того, чтобы отделить адрес от номера порта. Если номер порта не указан, то скобки тоже можно не использовать. Кроме того, если строка хоста задаётся через командную строку, то в некоторых оболочках может потребоваться экранировать эти скобки.Примечание: Раздел между именем пользователя и именем хоста происходит по последнему найденному знаку @, так что можно вполне использовать email адрес в качестве имени пользователя.В процессе выполнения Fabric нормализует полученную строку хоста и затем сохраняет каждую часть (имя пользователя / имя хоста / порт) в словаре окружения и для их использования и для того, чтобы задачи по необходимости могли на них сослаться. Более детально смотри в «Словарь окружения«.Роли
Строка хоста определяют один хост, но иногда бывает полезно объединить хосты в группы. Возможно, у Вас есть несколько Web серверов за балансировщиком нагрузки, и Вы хотите обновить их все; или Вы хотите запустить задачу на «всех клиентских серверах». Роли пFabric: Обзор и руководство (Перевод)
Добро пожаловать в Fabric!
Этот документ - быстрый тур по возможностям Fabric и короткое руководство по его использованию. Дополнительная документация может быть найдена тут.
Что такое Fabric?
Как написано в README:
Fabric — это библиотека для Python (2.5 или выше) и инструмент командной строки для использования SSH при развёртывании приложений или выполнении административных задач.
Более конкретно:- Инструмент, который позволяет Вам выполнить любую функцию Python при помощи командной строки
- Библиотека подпрограмм (построенная на более низкоуровневой библиотеке), переназначенная для выполнения команд оболочки через SSH легко и по-питонски.
Обычно, большинство пользователей используют обе эти возможности, применяя Fabric для записи и выполнения функций Python или заданий, чтобы автоматизировать работу с удалённым сервером. Давайте на это посмотрим.Hello, fab
Это не было бы хорошим руководством без стандартного примера:def hello():print(«Hello world!»)Если разместить эту функцию в модуле с именем fabfile.py в вашей рабочей директории, то эту функцию hello можно выполнить при помощи инструмента fab (устанавливаемого как часть Fabric) и будет делать именно то, что Вы ожидаете:$ fab helloHello world!Done.Вот и всё. Таким образом Вы можете использовать Fabric как (очень) простой способ сборки даже без импорта какого либо из его API.Примечание: Инструмент fab просто просто импортирует ваш fabfile и выполняет функцию или функции, которые Вы в нём определили. Тут нет никакой магии — всё, что Вы можете сделать в обычном скрипте Python, можно сделать и в fabfile.Аргументы задачи
Очень часто полезно передать параметры в процессе выполнения в вашу задачу, как Вы это можете сделать и в обычном скрипте Python. Fabric поддерживает эту возможность при помощи такой нотации:: , = ,…. Давайте расширим наш первый пример: def hello(name=»world»):print(«Hello %s!» % name)По умолчанию, если Вы используете команду fab hello — Вы получите тот же результат, что и в раньше; но теперь Вы можете передать и имя, кого приветствовать:$ fab hello_name=JeffHello Jeff!Done.Те, кто уже программируют на Python, могут предположить, что то же самое можно сделать и немного по другому:$ fab hello:JeffHello Jeff!Done.На данный момент, аргумент, который Вы передаёте, в любом случае будет передан как строка, так что Вам могут потребоваться дополнительные манипуляции с полученным значением. В более поздних версиях может быть добавлена система типов, чтобы облегчить этот процесс.См также: аргументы для задачиЛокальные команды
В примере выше fab всего лишь экономит Вам несколько строк, начинающихся после `if __name__==»__main__»`. Обычно же используется API Fabric, который содержит функции (или операции) для выполнения команд оболочки, передачи файлов и т.д.Давайте построим гипотетическое Web приложение fabfile. Этот сценарий делает следующее: Web приложение управляется через Git на удалённом хосте vcshost. На localhost у нас есть локальный клон web-приложения.wxPython in Action. Глава 13. Создание списков (list control) и управление им (Перевод)
В этой главе мы поговорим о:
- создании списков в различных стилях
- работа с элементами в списке
- реакции на выбор пользователем элемента из списка
- редактирование меток и сортировка списка
- создание большого списка (large list)
У всех нас есть списки, которые мы хотим просмотреть, и программисты на wxPython не исключение. В wxPython есть два управляющих элемента, которые Вы можете использовать для отображения информации при помощи списков. Самый простой — list box — обычный список из одной колонки, который можно прокручивать, похожий на то, что Вы можете получить в HTML при помощиЭта глава будет говорить о более сложном способе отображения информации в форме списка — элементе управления list (list control), полноценном виджете списка. Он отображает ListCtrl с несколькими колонками информации для каждой строки, который можно отсортировать по каждой колонке и стиль отображения которого можно настроить. У Вас есть достаточно гибкости в настройке каждой части этого элемента.13.1 Создание элемента управления list
List может быть создан в одной из 4-х форм:- иконка (плитка)
- маленькая иконка (значки)
- список
- отчёт
Суть этого должна быть понятна всем, кто использует Проводник в Windows или Mac Finder — это соответствует способам отображения элементов в проводнике. Мы начнём наше исследование этого элемента с того, что посмотрим как его создать в каждой из этих форм.13.1.1 Что такое режим «иконка»
List выглядит как панель отображения дерева файловой системы в MS Windows Explorer. Этот элемент управления отображает информацию в одном из четырёх режимов. По умолчанию используется режим иконка, где каждый элемент списка представлен иконкой с текстом под ней. Рисунок 13.1 показывает простой пример этого режима.
Код для отображения этого примера приведён в листинге 13.1. Обратите внимание, что этот код зависит от некоторых .png файлов, которые расположены в той же папке, что и наш модуль. Эти файлы можно получить с сайта этой книги.Листинг 13.1import wximport sys, globclass DemoFrame(wx.Frame):def __init__(self):wx.Frame.__init__(self, None, -1,«wx.ListCtrl in wx.LC_ICON mode»,size=(600,400))il = wx.ImageList(32,32, True)# Создаём image listfor name in glob.glob(«icon??.png»):bmp = wx.Bitmap(name, wx.BITMAP_TYPE_PNG)il_max = il.Add(bmp)# Создаём listself.list = wx.ListCtrl(self, -1style=wx.LC_ICON | wx.LC_AUTOARRANGE)self.list.AssignImageList(il, wx.IMAGE_LIST_NORMAL)for x in range(25):# Заполняем listimg = x % (il_max+1)self.list.InsertImageStringItem(x,«This is item %02d» % x, img)app = wx.PySimpleApp()frame = DemoFrame()frame.Show()app.MainLoop()
Рисунок 13.1 Простой список в режиме «иконка» В листинге 13.1 демонстрационный фрейм создаёт список изображений (image list), который содержит ссылки на изображения, которые мы будем отображать; затем мы создаём и заполняем элемент list. Список изображения мы обсудим позже в этой главе.
13.1.2 Что такое режим «маленькая иконка»
Режим «маленькая иконка» (small icon) похож на режим «иконка», только использует маленькие значки. Рисунок 13.2 приводит пример того же самого списка в режиме «маленькой иконки».Этот режим особенно полезен когда Вы хотите уместить в виджете много элементов, особенно если сами иконки не настолько детализированы, чтобы показывать их в исходном размере.
Рисунок 13.2 Простой list в режиме «маленькая иконка» 13.1.3 Что такое режим списка (list mode)?
В режиме списка элементы отображаются в нескольких колонках, автоматически заполняя каждую из них по очереди, как показано на рисунке 13.3Этот режим имеет те же достоинства, что и режим «маленькая иконка»; выбор между ними (т.е. между расположением в строчку или в столбик) зависит от ваших предпочтений.13.1.4 Что такое режим отчёта (report mode)?
В режиме отчёта list отображается в формате нескольких колонок, где каждый строк может иметь любое число столбцов, связанных с ним, как показано на рисунке 13.4
Рисунок 13.4 Простой list в режиме «отчёт» Этот режим настолько отличается от режима «иконка», что стоит привести код, который нужен для создания такого отображения:
Листинг 13.2 Пример создания list'a в режиме «отчёт»import wx
import sys, glob, random
import data
class DemoFrame(wx.Frame):
def __init__(self):
wx.Frame.__init__(self, None, -1,
«wx.ListCtrl in wx.LC_REPORT mode»,
size=(600,400))
il = wx.ImageList(16,16, True)
for name in glob.glob(«smicon??.png»):
bmp = wx.Bitmap(name, wx.BITMAP_TYPE_PNG)
il_max = il.Add(bmp)
# Создаём list
self.list = wx.ListCtrl(self, -1, style=wx.LC_REPORT)
self.list.AssignImageList(il, wx.IMAGE_LIST_SMALL)
# Добавляем колонки
for col, text in enumerate(data.columns):
self.list.InsertColumn(col, text)
# Добавляем строки
for item in data.rows:
index = self.list.InsertStringItem(sys.maxint, item[0])
for col, text in enumerate(item[1:]):
self.list.SetStringItem(index, col+1, text)
# даём каждому элементу случайное изображение
img = random.randint(0, il_max)
self.list.SetItemImage(index, img, img)
# Настраиваем ширину колонок
self.list.SetColumnWidth(0, 120)
self.list.SetColumnWidth(1, wx.LIST_AUTOSIZE)
self.list.SetColumnWidth(2, wx.LIST_AUTOSIZE)
self.list.SetColumnWidth(3, wx.LIST_AUTOSIZE_USEHEADER)
app = wx.PySimpleApp()
frame = DemoFrame()
frame.Show()
app.MainLoop()В следующем разделе мы обсудим как поместить значение в соответствующем месте. Логика отображения этого режима должна быть не так уж и сложна. Лучше всего использовать этот режим в случае, когда список содержит одну-две дополнительные колонки данных. Если же ваш список сложнее, или содержит больше данных, то тогда лучше использовать grid control, описанный в 14 главе.13.1.5 Как я могу создать list?
Элемент list в wxPython является экземпляром класса wx.ListCtrl. Его конструктор похож на конструкторы других виджетов:wx.ListCtrl(parent, id, pos=wx.DefaultPosition, size=wx.DefaultSize, style=wx.LC_ICON, validator=wx.DefaultValidator, name=»listCtrl»)Эти параметры содержат значения, которые мы уже видели в конструкторах других виджетов. parent — это родительский виджет, в котором будет расположен list; id — идентификатор wxPython, где -1 обозначает автоматически сгенерированное значение. Явно расположение задаётся параметрами pos и size. style задаёт режим и остальные опции отображения — об этом мы ещё поговорим в этой главе. validator используется для проверки ввода и о нём мы говорили в 9 главе. Параметр name используется достаточно редко.Флаг style — это битовая маска, которая определяет некоторые возможности этого элемента управления. Первый набор значений — это режим отображения элемента. Режим по умолчанию — wx.LC_ICON. Таблица 13.1 содержит остальные доступные режимы.Стиль Описание wx.LC_ICON Режим «иконка» wx.LC_LIST Режим «список» wx.LC_REPORT Режим «отчёт» wx.LC_SMALL_ICON Режим «маленькая иконка» В режимах «иконка» и «маленькая иконка» доступны ещё три флага, которые определяют расположение иконки относительно списка. Значение по умолчанию — wx.LC_ALIGN_TOP, которе выравнивает иконки по вершине списка. Для выравнивания по левой стороне используйте wx.LC_ALIGN_LEFT. Стиль LC.AUTOARRANGE заворачивает иконки по достижении ими нижнего или правого угла окна.Таблица 13.2 содержит стили отображения для режима «отчёт»:Стиль Значение по умолчанию wx.LC_HRULES Рисуе
т линии между строками list'awx.LC_NO_HEADER Не отображает заголовки колонок wx.LC_VRULES Рисует линии между колонками list'a Флаги битовых масок могут быть скомбинированы при помощи операции или. Используйте wx.LC_REPORT | wx.LC_HRULES | wx.LC_VRULES для того чтобы получить вид, похожий на решётку. По умолчанию все элементы list позволяют осуществлять множественный выбор. Для того, чтобы это изменить используйте флаг wx.LC_SINGLE_SEL.
В отличие от остальных виджетов, которые мы видели до сих пор, list имеет ещё несколько методов, которые позволяют Вам изменить его флаги стилей уже в процессе выполнения. Метод SetSingleStyle(style, add=True) позволяет Вам добавить или удалить один флаг стиля, в зависимости от параметра add. Вызов listCtrl.SetSingleStyle(LC_HRULES, True) добавит горизонтальную линейку, тогда как listCtrl.SetSingleStyle(LC_HRULES, False) удалит её. Вызов SetWindowStyleFlag(style) позволяет Вам переустановить весь стиль, задав новые флаги, например, SetWindowsStyleFlag(LC_REPORT | LC_NO_HEADER). Эти методы полезны для изменения list'a на лету.13.2 Управление элементами в list'e
После того, как list создан, Вы можете добавлять информацию в него. В wxPython для этой цели используются разные способы, зависящие от того, что Вы хотите добавить — текстовую информацию или изображения, ассоциированные с элементами list'a. В следующих разделах мы покажем как добавлять текст и изображения в ваш list.13.2.1 Что такое image list и как к нему добавлять изображения
Перед тем, как мы сможем говорить о том, как информация добавляется в list, мы должны сказать несколько слов о том, как list работает с изображениями. Все изображения, используемые в этом элементе, должны быть сперва добавлены в image list, который представляет из себя проиндексированный массив изображений, сохранённых в элементе list. Когда Вы связываете изображение с определённым элементом в list, то для ссылки на изображение используется его индекс. Этот механизм позволяет быть уверенным в том, что каждое изображение загружено только один раз, вне зависимости от того, как часто оно используется в list. Что, в свою очередь, помогает сэкономить память в случаях, когда изображения используются по нескольку раз. Кроме того, это обегчает связь между несколькими версиями одного и того же изображения, что может быть полезно для различных режимов. Более подробно создание изображений и bitmap в wxPython обсуждается в главе 12.Создание image list
image list является экземпляром wx.ImageList и для его создания используется следующий конструктор:
wx.ImageList(width, height, mask=True, initialCount=1)
Параметры width и height задают в пикселях размер изображения, которое будет добавлено в list. Изображения больше, чем указанный размер добавить нельзя. Если параметр mask = True, nj изображение рисуется с его маской, если она у него есть. Параметр initialCount задаёт начальный внутренний размер list'a. Если Вы знаете, что list будет большой, то указание этого размера может сэкономить память и время позже.Добавление и удаление изображений
Вы можете добавить изображение в list при помощи метода Add(bitmap, mask=wx.NullBitmap), где bitmap и mask оба являются экземплярами wx.Bitmap. Аргумент mask является монохромным битовым изображением, которое определяет прозрачные части изображения, если они должны быть. Если битовое изображение уже имеет свою маску, то его маска и будет использоваться по умолчанию. Если маски у изображения нет и у Вас нет монохромной карты прозрачности, но Вы хотите чтобы какой-то цвет в изображении служил маской, Вы можете использовать метод AddWithColourMask(bitmap, colour), где colour — цвет wxPython (или его имя), который будет использоваться в качестве маски. Если у Вас есть объект wx.Icon, который Вы хотите добавить в image list, то используйте метод AddIcon(icon). Все методы добавления возвращают индекс изображения в list'e, который Вы можете позже использовать.Следующий отрывок кода показывает пример создания image list (похоже на листинг 13.1)il = wx.ImageList(32, 32, True)
for name in glob.glob(«icon??.png»):
bmp = wx.Bitmap(name, wx.BITMAP_TYPE_PNG)
il_max = il.Add(bmp)image list должен быть привязан к list при помощи следующего метода:self.list.AssignImageList(il, wx.IMAGE_LIST_NORMAL)Для того, чтобы удалить изображение из image list, воспользуйтесь методом Remove(index), где index — индекс изображения в списке. Этот метод изменяет индексы всех изображений после удалённого, что может создать проблему,Django 1.5 и Python 3 (Перевод)
Django 1.5 уже «полностью» поддерживает Python 3, как минимум с технической точки зрения. Поддержка реализована, проверена и работает. Я планирую поместить свой сайт на Django 1.5 / Python 3.3 уже в этом году. Так что в этом смысле всё «готово».Однако, это не значит, что я рекомендую делать это другим.У мы даём серьёзные обещания обратной совместимости и мы ещё не на 100% хорошо соответствуем Python 3 API. Есть маленькая (не нулевая) вероятность, что надо будет что-то изменить между 1.5 и 1.6; и мы бы хотели сохранить возможность обратной несовместимости (для Python 3).Кроме того, есть маленькая (но, опять же, не нулевая) вероятность что есть 1-3 серьёзрых бага в поддержке Python 3 и мы не хотим, чтобы люди с этим столкнулись.Наконец, значительная часть «хорошести» Django — сторонние приложения, многие из которых не поддерживают ещё Python 3. И это серьёзная проблема для Django / Py3, так как многие сайты используют большое количество сторонних приложений. Так что перед переходом на Python 3 Вы должны решить для себя вопрос: «Готов ли я отказаться от этого приложения или готов портировать его на Python 3 и внести патч?»В случае моего сайта я к этому готов. Я достаточно хорошо знаю Django, чтобы не бояться потенциальных багов и обратной несовместимости и я могу заняться патчами для Python 3.Но к большинству пользователей это не относится, так что я надеюсь, что большая часть пользователей Django дождётся 1.6 перед тем, как начать использовать Python 3.У нас пока нет твёрдых сроков. Я думаю, что 1.6 можно ждать где-то через 6-9 месяцев, но это зависит от слишком многих факторов. Реально срок может быть и год и 3-4 месяца. Увидим 🙂Автор: Ishayahu Lastov



