RSS
[>] Re: эха про python
python.15
Andrew Lobanov(station13, 1) — Roman Yakovlev
2015-09-11 08:26:56


>>Сразу же вопрос: насколько оптимизированы всякие штуки, как то приведение типов или методы .split/.join? Просто порой мне начинает казаться, что я увязаю в болоте синтаксического сахара, но при этом не уверен, что внутри этого всего нет оптимизированных низкоуровневых реализаций, а значит моя высокоуровневая реализация таких штук "по-старинке" будет медленнее.
>это идеология. :) всё, что укладывается в pep8 и pep20 - питоноугодно. всё, что нет - нет
Поутру перечитал и решил добавить. Вопрос сугубо технический =) Если его перефразировать, то звучит примерно так:

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

number_length(num):
    return len(str(num))

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

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

number_length(num):
    n = 0
    while num > 0:
        n = n + 1
	num = num // 10
    return n

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

P.S.: Кто-то классическое решение такой задачки мне даже лайкнул на checkio.org.

[>] Re: эха про python
python.15
Roman Yakovlev(station13, 11) — Andrew Lobanov
2015-09-11 09:49:56


>Я привык считать приведение типов, работу с нетипизированными массивами (читай списками) медленными операциями. Определение длинны строки -- медленная операция. Но вот, например, классическая задачка по программированию: определить разряд числа. Классическим питон-решением является:

какое очевидное - такое и правильное :) дзен python :)

со списками... поэтому у тебя в python аж три списка - list, tuple и set :) посмотри, с какой скоростью сравниваются два set-а по 200000 значений в них ;)


не, я теорией не интересуюсь, мне важнее практика. какой вариант читабельнее - тот и лучше, pep8 и pep20 не зря являются основой основ :)

>Вот и вопрос отсюда: как оптимальнее с точки зрения питона? Конечно, я бы мог написать несколько тестов для проверки этого факта, но всегда было интересно мнение непосредственно питонщиков по этому вопросу.

мнение тех, кто постиг дао, дзен, pep8 и pep20, думаю, будет однозначным - какое читабельнее, то и лучше. для скорости - расширения C и разные numpy, а в обычных вещах никто на спичках экономить не будет (разумеется, если это не сверхнеоптимальное решение)

[>] Re: эха про python
python.15
Roman Yakovlev(station13, 11) — Andrew Lobanov
2015-09-10 21:53:34


>>всем привет!
>Привет.

>Сразу же вопрос: насколько оптимизированы всякие штуки, как то приведение типов или методы .split/.join? Просто порой мне начинает казаться, что я увязаю в болоте синтаксического сахара, но при этом не уверен, что внутри этого всего нет оптимизированных низкоуровневых реализаций, а значит моя высокоуровневая реализация таких штук "по-старинке" будет медленнее.

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

[>] Расстановка сообщений в эхе в правильном порядке
python.15
vit01(mira, 1) — All
2015-12-04 14:13:07


$ mkdir echo_new # и дальше

#!/usr/bin/python2
# -*- coding:utf8 -*-
from ii_functions import *
import os

echolist=os.listdir(indexdir)

for echo in echolist:
	print("doing "+echo)
	msgids=getMsgList(echo)
	msgs={}
	
	for msgid in msgids:
		msg=getMsg(msgid)
		msg["time"]=int(msg["time"])
		msgs[msgid]=msg
	
	def sortTime(msgid):
		return msgs[msgid].get("time")
	
	msgids.sort(key=sortTime)
	
	open("echo_new/"+echo, "w").write("\n".join(msgids)+"\n")

ii_functions.py подойдёт отсюда https://github.com/vit1-irk/ii-db-utils или из Qt-клиента.

[>] Re: эха про python
python.15
Andrew Lobanov(station13, 1) — Roman Yakovlev
2015-09-10 21:49:14


>всем привет!
Привет.

Сразу же вопрос: насколько оптимизированы всякие штуки, как то приведение типов или методы .split/.join? Просто порой мне начинает казаться, что я увязаю в болоте синтаксического сахара, но при этом не уверен, что внутри этого всего нет оптимизированных низкоуровневых реализаций, а значит моя высокоуровневая реализация таких штук "по-старинке" будет медленнее.

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

[>] Re: эха про python
python.15
Roman Yakovlev(station13, 11) — Andrew Lobanov
2015-09-10 22:01:52


>>ps. ты, кстати, пишешь, на python2 а не python3 :) в python3 нет всех этих .decode, поэтому я даже не понимаю, почему оно работает (но в python3 я не вникал и не интересуюсь особо). по идее, это можно портировать на python2, надо будет попробовать
>Ну фиг знает. Это кушает python3. И это я очень долго и упорно всё гуглил и обкатывал. И они таки есть. Потому как байт-массив из юникода не получается и потому приходится промежуточно транслировать всё в ascii. Уж не знаю тонкостей, но работает.

именно поэтому я выбираю python2. там всё просто - str это байт-строка, unicode это unicode-строка. в python3 столько заморочек по этому поводу, что проще повеситься. поэтому, когда стоят такие задачи, python2 - то, что доктор прописал. а сейчас это в python2 не запускается :(

[>] Вопрос знатокам эхотага
python.15
Andrew Lobanov(station13, 1) — All
2016-01-21 09:10:13


Сабж: если я разбиваю программу на несколько логически раздельных файлов, но хочу использовать одни и те же библиотеки в них, я должен импортировать их повторно в каждом файле. Насколько это экономично? Они подгружаются каждый раз отдельно?

[>] Re: регекспы
python.15
vit01(mira, 1) — Roman Yakovlev
2015-11-16 16:49:34


RY> а как сделать "или 8, или 20"?
Вроде бы, надо отдельные группы городить, но точно не уверен.

([A-Z]{8})|([A-Z]{20})

[>] rsa и все все все
python.15
Roman Yakovlev(station13, 11) — All
2015-09-10 21:48:40


всем привет в новой эхе

подскажите какой-нибудь алгоритм шифрование и лёёёгонькую библиотечку python для него, чтобы был небольшой паблик-кей, какой-нибудь привейт-кей и можно было слать шифровки на паблик-кей

ща я пробую с python-rsa, в debian она есть, а вот в openbsd её нет :) но может есть способы проще

[>] Пишем плагин для Sensu
python.15
Difrex(mira, 14) — All
2015-10-13 13:47:54


Думал, куда бы перетащить эту статью -- в linux.14 или в python.15. Решил остановиться на питоне.

Итак:

Будем писать на питоне.

Нам потребуется пакет sensu-plugin-python. Ставим его. У меня он опакечен, вам же предстоит это делать самому. Взять его можно на гитхабе: https://github.com/sensu/sensu-plugin-python.git.

*Пишем проверку*

#!/usr/bin/python
# -*- coding: utf-8 -*-
 
from sensu_plugin import SensuPluginCheck
from os import listdir
from os.path import isfile,join
 
class CoolCheck(SensuPluginCheck):
  def setup(self):
    self.parser.add_argument(
      '-w',
      '--warning',
      required=True,
      type=int,
      help='Integer warning level to output'
    )
    self.parser.add_argument(
      '-c',
      '--critical',
      required=True,
      type=int,
      help='Integer critical level to output'
    )
    self.parser.add_argument(
      '-d',
      '--directory',
      required=True,
      type=str,
      help='Path to directory'
    )
 
 
  def run(self):
    self.check_name('my_cool_check')
 
    dir = self.options.directory
 
    onlyfiles = [ f for f in listdir(dir) if isfile( join(dir, f) ) ]
    size = len(onlyfiles)
 
    if size < self.options.warning:
      self.ok() # Exit code 0
    elif size >= self.options.warning and size < self.options.critical:
      self.warning('Files count ' + str(size)) # Exit code 1
    elif size >= self.options.critical:
      self.critical('Files count ' + str(size)) # Exit code 2
    else:
      self.unknown('Unknown error')
 
if __name__ == "__main__":
  f = CoolCheck()

SensuPluginCheck уже предоставляет нам парсер командной строки по-этому нет необходимости использовать python-argparse или что-то еще подобное.

Функция *setup()* из класса *CoolCheck()* выполняется первой при запуске программы. В ней мы как раз задаем аргументы, какие будет принимать наша проверка.

В Функции *run()* уже выполняется сама проверка. Мы проверяем количество файлов в указанной директории, сравниваем с пороговыми значениями и выходим с соответствующим кодом выхода и сообщением.

*Метрики*

Адаптируем код проверки под метрику и вынесем код подсчета количества файлов в отдельную функцию.
cool.py:
from os import listdir
from os.path import isfile,join
def files_count(dir):
    onlyfiles = [ f for f in listdir(dir) if isfile( join(dir, f) ) ]
    size = len(onlyfiles)
     
    return size

И сам плагин метрики.
cool_metric.py:
#!/usr/bin/python
# -*- coding: utf-8 -*-
 
from sensu_plugin import SensuPluginMetricGraphite
from cool import files_count
 
class CoolMetricGraphite(SensuPluginMetricGraphite):
    def setup(self):
      self.parser.add_argument(
        '-s',
        '--schema',
        required=True,
        type=str,
        help='Graphite schema'
      )
       
      self.parser.add_argument(
        '-d',
        '--directory',
        required=True,
        type=str,
        help='Path to directory'
      )
  
 
    def run(self):     
        size = files_count(self.options.directory)
        self.output(self.options.schema, size)
        self.ok()
 
 
if __name__ == "__main__":
     f = CoolMetricGraphite()

Попробуем запустить:
chmod +x cool_metric.py
./cool_metric.py -s `hostname -f`.tmp.files -d /tmp
example.com.tmp.files    2    1442480739

Все отлично! Осталось только опакетить(не забывай только добавлять в зависимость sensu-plugin-python), привезти пакет на нужные хосты и написать конфиг Sensu и повесить графитовый хандлер
{
  "checks": {
    "cool_metrics": {
      "type": "metric",
      "handler": "graphite",
      "command": "/etc/sensu/plugins/other/cool.py -s \"`hostname -f`.tmp.files\" -d /tmp",
      "interval": 60,
      "subscribers": [
        "cool_hosts"
      ]
    }
  }
}

Аналогично делаем для проверки.



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

sensu-plugin-python реально упрощает жизнь.

В следующий раз будем писать хандлер.

[>] Re: эха про python
python.15
Andrew Lobanov(station13, 1) — Roman Yakovlev
2015-09-10 21:57:11


>ps. ты, кстати, пишешь, на python2 а не python3 :) в python3 нет всех этих .decode, поэтому я даже не понимаю, почему оно работает (но в python3 я не вникал и не интересуюсь особо). по идее, это можно портировать на python2, надо будет попробовать
Ну фиг знает. Это кушает python3. И это я очень долго и упорно всё гуглил и обкатывал. И они таки есть. Потому как байт-массив из юникода не получается и потому приходится промежуточно транслировать всё в ascii. Уж не знаю тонкостей, но работает.

[>] Re: эха про python
python.15
Roman Yakovlev(station13, 11) — Andrew Lobanov
2015-09-10 21:53:35


>Сразу же вопрос: насколько оптимизированы всякие штуки, как то приведение типов или методы .split/.join? Просто порой мне начинает казаться, что я увязаю в болоте синтаксического сахара, но при этом не уверен, что внутри этого всего нет оптимизированных низкоуровневых реализаций, а значит моя высокоуровневая реализация таких штук "по-старинке" будет медленнее.

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

это идеология. :) всё, что укладывается в pep8 и pep20 - питоноугодно. всё, что нет - нет

ps. ты, кстати, пишешь, на python2 а не python3 :) в python3 нет всех этих .decode, поэтому я даже не понимаю, почему оно работает (но в python3 я не вникал и не интересуюсь особо). по идее, это можно портировать на python2, надо будет попробовать

[>] регекспы
python.15
Roman Yakovlev(lenina,1) — All
2015-11-16 04:38:22


Вот {8} - это 8 символов
{8,20} - это от 8 до 20
а как сделать "или 8, или 20"?

[>] Re: rsa и все все все
python.15
Andrew Lobanov(station13, 1) — Roman Yakovlev
2015-09-10 21:50:48


>подскажите какой-нибудь алгоритм шифрование и лёёёгонькую библиотечку python для него, чтобы был небольшой паблик-кей, какой-нибудь привейт-кей и можно было слать шифровки на паблик-кей
>ща я пробую с python-rsa, в debian она есть, а вот в openbsd её нет :) но может есть способы проще
Немного неэхотаг, на у меня мелькали мысли прикрутить просто PGP для этих целей. Да-да. Прямо к ii-софту =)

[>] Re: rsa и все все все
python.15
vit01(mira, 1) — Roman Yakovlev
2015-09-11 07:24:49


Попробуй PyCrypto. Я, правда, не использовал RSA через него, но с AES он отлично справляется.

[>] Re: Qt и QProgressDialog
python.15
vit01(mira, 1) — vit01
2016-01-08 14:19:13


vit01> после этого эхи стали открываться раз в 5 дольше, чем без него.

Понял, в чём была проблема.
Когда решил вынести это дело в отдельный поток и попробовать снова, результат оказался точно таким же. Как оказалось, тормоза вызывало не обновление прогрессбара, а прорисовка QListWidget. Да, да, который был во время этого процесса бесполезен. Так что я теперь просто скрываю MainWindow во время подгрузки данных, а после этого опять делаю видимым, и всё работает нормально.

[>] Re: rsa и все все все
python.15
Difrex(mira, 14) — Roman Yakovlev
2015-09-14 16:33:31


Дергай gpg. У GPG стандартизированный API и он есть везде.

[>] Ликвидируем дубли в эхах по сабжу и тексту сообщения
python.15
vit01(mira, 1) — All
2015-12-05 19:00:54


#!/usr/bin/python2
# -*- coding:utf8 -*-
from ii_functions import *
import os

echolist=os.listdir(indexdir)

for echo in echolist:
		print("doing "+echo)
		msgids=getMsgList(echo)
		arr=[]
		doubles=0

		for msgid in msgids:
				msg=getMsg(msgid)

				if [msg["msg"], msg["subj"]] in arr:
						doubles+=1
						msgids.remove(msgid)
						print msgid
				else:
						arr.append([msg["msg"], msg["subj"]])

		if doubles>0:
				print("doubles: "+str(doubles))
				open("echo_new/"+echo, "w").write("\n".join(msgids)+"\n")

[>] Qt и QProgressDialog
python.15
vit01(mira, 1) — All
2015-09-18 15:53:43


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

=)

[>] эха про python
python.15
Roman Yakovlev(station13, 11) — All
2015-09-10 21:46:23


всем привет!

[>] Re: Код, возвращаемый приложением
python.15
vit01(mira, 1) — Andrew Lobanov
2016-03-21 16:15:49


p=subprocess.Popen(блаблабла)
p.wait()
print(p.returncode)

Но вот зачем...

[>] sqlite3
python.15
Andrew Lobanov(tavern,1) — All
2016-06-12 16:19:28


Что-то в сабже очень грустно работает подсчёт строк в таблице. Каких-то 42+к записей на нетбуке считает около пяти секунд. Есть спобос быстрого подсчёта строк в связке python3 и sqlite3?

[>] Re: sqlite3
python.15
Andrew Lobanov(tavern,1) — vit01
2016-06-13 10:58:29


vit01> Ты делаешь просто SELECT COUNT(*) from ... ? Можно попробовать создать индекс в БД и проделывать хаки с ним.

Печальней даже стало. Подсчёт длины выборки стал быстрее раза в два (всё равно около 2-3 секунд), но существенно просела скорость добавления записей.

vit01> Может быть, здесь что-то полезное тебе есть: http://www.sqlite.org/cvstrac/wiki?p=PerformanceTuning

Спасибо. Почитаю как посвободней станет.


Как вы уже наверняка догадались, я пытаюсь прикрутить sqlite к цезию. В целом доработки минимальные требуются, и всё работает просто отлично, кроме подсчёта длины индекса. Надо думать как обойти сие досадное недоразумение, так как в целом мне такое положение дел понравилось.

2vit01: У тебя есть какие-нибудь наработки по формату базы? Может, есть смысл посмотреть в сторону твоей реализации ноды?

[>] filler у операции %
python.15
Andrew Lobanov(tavern,1) — All
2016-04-26 11:10:27


Если я хочу сделать отступ при выводе информации, то я использую нечто вроде

"%-20s%s" % (1, 2)

Но при этом между символами 1 и 2 будут пробелы. Как заполнить пространство между ними произвольным символом без написания своей функции форматирования и возможно ли это в принципе?

[>] Re: sqlite3
python.15
vit01(mira, 1) — Andrew Lobanov
2016-06-13 11:21:24


AL> У тебя есть какие-нибудь наработки по формату базы? Может, есть смысл посмотреть в сторону твоей реализации ноды?

Вот так создаётся база в ii-php:

CREATE TABLE IF NOT EXISTS `$db->tablename` (
       `number` bigint NOT NULL auto_increment,
       `id` varchar(20) NOT NULL,
       `tags` text,
       `echoarea` text NOT NULL,
       `date` varchar(30) NOT NULL default '0',
       `msgfrom` text,
       `addr` text,
       `msgto` text,
       `subj` text not NULL,
       `msg` text not NULL,
        primary key(number, id)
	) ENGINE InnoDB default charset='utf8';
");

Для sqlite, конечно же, следует изменить типы данных (в том числе из-за производительности). Насчёт поля date я подставил varchar(30), чтобы избежать проблемы 2038, но это может быть неудобно для поиска, так что здесь надо бы что-нибудь другое. И с primary key тоже свои особенности должны быть.

[>] И снова по импорту
python.15
vit01(mira, 1) — All
2016-01-22 09:52:21


Есть файл first.py, там

def sample():
    print("123")

Есть файл second.py, там

from first.py import *

def wrapper(func):
    def wrapped(arg):
        open("file", "w").write(arg)
    return(wrapped)

print=wrapped(print)
sample()
print(" 22")

// мог ошибиться, пишу с телефона

Когда вызывается second.py, функция print внутри sample() сохраняет своё прежнее поведение. А внешний принт меняет.

Если заменить from blabla import * на import blabla; blabla.print=wrapped(print), то всё работает.

[>] Re: Вопрос знатокам эхотага
python.15
Andrew Lobanov(station13, 1) — Рома
2016-01-21 10:31:05


Рома> они подгружаются при первом вызове

Спасибо за ответ.

[>] Re: sqlite3
python.15
Andrew Lobanov(tavern,1) — vit01
2016-06-13 11:38:08


AL>> У тебя есть какие-нибудь наработки по формату базы? Может, есть смысл посмотреть в сторону твоей реализации ноды?

vit01> Вот так создаётся база в ii-php:

Примерно так ж поступил и я. Всё отлично работает, кроме подсчёта количества сообщений. Ладно. Буду дальше думать.

[>] webbrowser
python.15
vit01(mira, 1) — All
2016-07-30 23:04:53


import webbrowser

browser=webbrowser.GenericBrowser("termux-open-url")
browser.open("https://antizapret.info/")

// Это был толстый намёк на будущий парсер ссылок в Цезии. Кусок кода рабочий, конечно же.

[>] Re: регекспы
python.15
Andrew Lobanov(station13, 1) — vit01
2016-01-22 08:44:14


RY>> а как сделать "или 8, или 20"?
vit01> Вроде бы, надо отдельные группы городить, но точно не уверен.

vit01> ([A-Z]{8})|([A-Z]{20})

Только в порядке уменьшения диапазонов:

([A-Z]{20}|[A-Z]{8})

Вот такой вариант точно рабочий и подходит для этой конкретной ситуации.

[>] Re: Код, возвращаемый приложением
python.15
Andrew Lobanov(station13, 1) — vit01
2016-03-21 16:36:48


> Но вот зачем...

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

[>] Re: Вопрос знатокам эхотага
python.15
Рома(lenina,148) — Andrew Lobanov
2016-01-21 09:32:46


они подгружаются при первом вызове

можешь в модуле написать print 123
и импортировать его несколько раз

выполнится это только один раз

[>] Re: sqlite3
python.15
vit01(mira, 1) — Andrew Lobanov
2016-06-12 16:39:52


Ты делаешь просто SELECT COUNT(*) from ... ? Можно попробовать создать индекс в БД и проделывать хаки с ним.

Может быть, здесь что-то полезное тебе есть: http://www.sqlite.org/cvstrac/wiki?p=PerformanceTuning

[>] Re: регекспы
python.15
Andrew Lobanov(station13, 1) — Рома
2016-01-22 08:56:15


AL> ====
AL> ([A-Z]{20}|[A-Z]{8})
AL> ====

Более красивое решение, но требующее питоновой обвязки:

s = " " + msgid + " "
r = re.compile("( [a-zA-Z1-9]{8} | [a-zA-Z1-9]{20} )")

Включение пробелов избавит от включения больших по количеству символов строк.

// Спасибо flame из инстедоконфы.

[>] Re: Вопрос знатокам эхотага
python.15
Рома(lenina,148) — Andrew Lobanov
2016-01-21 09:31:57


> Они подгружаются каждый раз отдельно?

нет

[>] Re: webbrowser
python.15
vit01(mira, 1) — Andrew Lobanov
2016-08-10 14:09:19


AL> и что-то мне подсказывает, что

browser=webbrowser.GenericBrowser("termux-open-url")

AL> будет излишним =)


Уже пробовал без него запускать. И ссылка начинает открываться ... в Elinks. Если этот самый elinks удалить, то вообще открывать не будет.

Отличить Termux можно очень легко по переменным окружения. Например, есть специфичные переменные $ANDROID_DATA и $ANDROID_ROOT. Также в PATH и PREFIX интересные штуки есть. Дальше, думаю, ты разберёшься сам.

[>] Код, возвращаемый приложением
python.15
Andrew Lobanov(station13, 1) — All
2016-03-21 15:49:25


Как в питоне ловить сабж? Например, приложение возвращает 0 как сигнал о штатном завершении работы и мне надо его отловить.

[>] Пишем хандлер для Sensu
python.15
Difrex(mira, 14) — All
2016-01-28 16:53:28


Как и обещал, будем разбирать процесс создания хандлера.

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

Рассмотрим ситуацию, когда нам надо запускать хандлер на события OK и CRITICAL. Пример конфигурации:
{
  "checks": {
    "cpu": {
      "handlers": ["email"],
      "command": "/etc/sensu/plugins/system/check-cpu.rb",
      "interval": 60,
      "subscribers": [
        "base"
      ]
    }
  }
}

Проверка запускается раз в 60 секунд.
{
    "handlers": {
        "email": {
            "type": "pipe",
            "command": "/etc/sensu/handlers/notification/mailer.pl",
                "severities": ["critical", "ok"]
        }
    }
}
При наступлении события смены состояния чека ok<->critical выхлоп проверки в формате JSON отправится на STDIN программе mailer.pl.

Как же выглядит выхлоп? А вот так:
$VAR1 = {
          'check' => {
                       'status' => 2,
                       'handlers' => [
                                       'test'
                                     ],
                       'subscribers' => [
                                          'test'
                                        ],
                       'interval' => 60,
                       'history' => [
                                      '0',
                                      '0',
                                      '0',
                                      '0',
                                      '0',
                                      '0',
                                      '0',
                                      '0',
                                      '0',
                                      '0',
                                      '0',
                                      '0',
                                      '0',
                                      '0',
                                      '0',
                                      '0',
                                      '0',
                                      '2',
                                      '2',
                                      '2',
                                      '2'
                                    ],
                       'issued' => 1442576325,
                       'executed' => 1442576325,
                       'total_state_change' => 5,
                       'duration' => '0.086',
                       'name' => 'test_check',
                       'command' => '/etc/sensu/plugins/files/check-checksums.rb -f /tmp/testfile -h e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855',
                       'output' => 'Checksum CRITICAL: /tmp/testfile does not match
'
                     },
          'action' => 'create',
          'client' => {
                        'timestamp' => 1442576321,
                        'address' => 'graphite.bingo-boom.ru',
                        'name' => 'graphite.bingo-boom.ru',
                        'version' => '0.20.0',
                        'subscriptions' => [
                                             'hp',
                                             'base',
                                             'uchiwa',
                                             'test',
                                             'dizard_snmp'
                                           ]
                      },
          'id' => '0139b1f9-db4c-4a2b-8124-a2c9b076e40d',
          'occurrences' => 4
        };
Теперь мы можем взять этот JSON и преобразовать его в объект. В python это будет выглядеть примерно так:
import ast
import fileinput

json = ''

for line in fileinput.input():
    json  += line

# Get dictionary from string
def get_dict(json):
        out_dict = ast.literal_eval(json)
    
        return out_dict


check_message_dict = get_dict(json)


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

Код из нашего продакшена – мылохандлера(немного устаревший код) https://github.com/Difrex/sensu/blob/master/handlers/mailer.pl

[>] Re: И снова по импорту
python.15
vit01(mira, 1) — vit01
2016-01-22 09:54:16


Вопрос: как сделать декоратор для подобной функции при поведении from module import * ?

[>] Re: webbrowser
python.15
Andrew Lobanov(tavern,1) — vit01
2016-08-10 13:43:24


vit01> // Это был толстый намёк на будущий парсер ссылок в Цезии. Кусок кода рабочий, конечно же.

Спасибо. Осталось разобраться как обнаруживать Termux, бо в linux и windows можно делать просто

webbrowser.open("url")

и что-то мне подсказывает, что

browser=webbrowser.GenericBrowser("termux-open-url")

будет излишним =)

Почитаю в ближайшее время что-нить на тему.

[>] Списки в функциях питона
python.15
Difrex(mira, 14) — All
2017-08-14 18:28:39


Зацените

import random


def get_port():
    port = random.randrange(33000, 37000, 1)
    return port


def check_list(port_list=[], count=0):
    if count == 0:
        print(port_list)

    port = get_port()

    if port in port_list:
        return "%s: %s in %s" % (count, port, len(port_list))
    else:
        count += 1
        port_list.append(port)
        return check_list(port_list, count)


print(check_list())
print(check_list())
print(check_list())

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

[>] Книги
python.15
btimofeev(tavern,13) — All
2017-04-06 20:53:22


ХамблБандл распродают книги по python: https://www.humblebundle.com/books/python-book-bundle

[>] Re: Списки в функциях питона
python.15
vit01(mira, 1) — Difrex
2017-08-14 20:29:15


Нихрена се. Интересное наблюдение.

Получается, после анализа кода интерпретатор создаёт пустой список [] и запоминает, где он лежит.

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

count всегда будет 0, потому что он примитив, а не полноценный объект, значит передаётся значением, а не по указателю

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

[>] Re: webbrowser
python.15
vit01(mira, 1) — vit01
2016-08-10 18:14:20


Можно ещё избежать всех этих проблем, добавив в конфиг параметр для браузера.

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

Иначе пишет в конфиг

browser termux-open-url
или
browser iceweasel

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