Простая напоминалка

Автор sx88, 12 февраля 2015, 17:29:40

« назад - далее »

0 Пользователи и 9 гостей просматривают эту тему.

sx88

Всем "здравствуйте" :)
По роду деятельности приходится держать много информации в голове и записной книжке. Но порой приходится вспомнить и сделать что-то в определенное время.
Покопавшись на просторах интернета нашел статью на ХАБРЕ (http://habrahabr.ru/post/240245/): человек сделал простую напоминалку на базе питона (два файла remindme.py и task в ):
remind.py
#!/usr/bin/env python
# -*- coding: utf-8 -*-
# RemindMe v1.5 created by Dennis Smal' in 2014 godgrace@mail.ru

from __future__ import print_function

import subprocess
import re
import sys

def replace_all(t, d):
    """Общая функция для подмены переменных"""
    for i, j in d.iteritems():
        t = t.replace(i, j, 1)
    return t

def get_datex(text):
    """Извлекает из текста дату и подстроку с датой, которую нужно удалить"""
    whatdate = ''
    delwhatdate = ''
    datex = re.findall(r'\d{2}[.,-]\d{2}[.,-]\d{4}|\d{1}[.,-]\d{2}[.,-]\d{4}',text) # ищем дату в формате 19.08.2014 или 19-08-2014 или 19,08,2014
    if datex:
        date = datex[0].replace('-','.').replace(',','.') # преобразуем дату в формат 19.08.2014
        whatdate = date
        delwhatdate = datex[0]+' '
    return whatdate, delwhatdate

def get_day(text):
    """Извлекает из текста день недели и подстроку, которую нужно удалить"""
    when = ''
    delday = ''

    day = re.findall('завтра|Завтра|в понедельник|во вторник|в среду|в четверг|в пятницу|в субботу|в воскресенье',text)
    daywithoutin = re.findall('понедельник|вторник|среда|четверг|пятница|суббота|воскресенье',text)
    if day:
        ind = {'завтра':'tomorrow', 'Завтра':'tomorrow', 'в понедельник':'mon', 'во вторник':'tue', 'в среду':'wed', 'в четверг':'thu', 'в пятницу':'fri', 'в субботу':'sat', 'в воскресенье':'sun'}
        when = replace_all(day[0], ind)
        delday = day[0]+' '
    elif daywithoutin:
    ind = {'понедельник':'mon', 'вторник':'tue', 'среда':'wed', 'четверг':'thu', 'пятница':'fri', 'суббота':'sat', 'воскресенье':'sun'}
        when = replace_all(daywithoutin[0], ind)
        delday = daywithoutin[0]+' '
    return (when, delday)

def get_clock(text):
    """Извлекает из текста время и подстроку, которую нужно удалить"""
    how = ''
    delclock = ''
    clock = re.findall('минуты |часа |дня |минуту |часов |день |минут |час |дней ',text)
    if clock: # смотрим, есть ли указание на часы, минуты, дни
        clockbank = {'минут ':'min', 'час ':'hour', 'дней ':'days', 'минуту ':'min', 'часа ':'hours', 'дня ':'days', 'минуты ':'min', 'часов ':'hours', 'день ':'days'}
        how = replace_all(clock[0], clockbank)
        delclock = clock[0]
    return (how, delclock)

def add_task(out, x):
    """Добавляет напоминание в очередь at"""
    #для отладки, чтобы долго не ждать
    #x = 'at now'
    #print (x)
    cmd = 'echo "DISPLAY=:0 ~/remindme/task %s" | %s' % (out, x)
    subprocess.Popen(cmd, shell=True)
   
       
def main(when="Через 15 минут", reminder=""):
    warn_cmd = [
            'zenity',
            '--warning',
            '--text="Попробуйте ещё раз.."'
            ]
    cmd = [
            'zenity',
            '--entry',
            '--title=Напоминалка',
            '--text=Введите напоминание',
            '--entry-text={} {}'.format(when, reminder),
            '--width=400'
            ]

    loop = True
    while loop:
        get = subprocess.check_output(cmd) # получаем текст
        text = get+' ' # добавляем в конец пробел, чтобы отрабатывать уведомления типа "напомнить мне через 10 минут". Если бы пробела не было, параметр clock был бы пуст. В параметре clock после слова "час" тоже стоит пробел, чтобы различать поиск "час" и "часов".
        find = re.findall('ерез [0-9]+|В [0-9:-]+|в [0-9:-]+|ерез час',text)

        if get: # убеждаемся, заполнено ли поле ввода
            if find: # убеждаемся, указано ли время напоминания
                what = find[0].split()
                timex = what[1].replace('-',':').replace('час','1')

                if len(timex) > 2: # заменяет выражения типа "в 10" на "в 10:00"
                    time = timex
                else:
                    time = timex+':00'
               
                whatdate, delwhatdate = get_datex(text)
                when, delday = get_day(text)
                how, delclock = get_clock(text)

                reps = {'ерез':'at now + %s %s' % (timex,how),'В':'at %s %s %s' % (time,when,whatdate),'в':'at %s %s %s' % (time,when,whatdate)}
                wors = {'Через %s %s' % (what[1],delclock):'','через %s %s' % (what[1],delclock):'','В %s ' % what[1]:'','в %s ' % what[1]:'', '%s' % delday:'', 'Через час':'', 'через час':'', '%s' % delwhatdate:'',} # какие слова мы будем удалять
                x = replace_all(what[0], reps) # это время, на которое запланировано появление напоминания
                out = replace_all(text, wors) # это текст напоминания

                add_task(out, x)
                loop = False

            else:
                error = subprocess.check_output(warn_cmd)
        else:
            loop = False

def usage():
    s = "Использование: {} [Время напоминания [Напоминание]]".format(__file__)
    print(s)

if __name__ == "__main__":
    if len(sys.argv) <= 3:
        main(*sys.argv[1:])
    else:
        usage()
[свернуть]

Task
#!/bin/bash
zenity --question --title=Напоминание --ok-label=Отложить --cancel-label=Ok --text="$*"
case $? in
0) ~/remindme/remind.py "Через 15 минут" "$*"
;;
1)
;;
esac
[свернуть]
их по умолчанию кладут в ~/remindme и ставят на исполнение. Запускаем remind.py и наслаждаемся.


Проблема : не появляется диалоговых окон.
При запуске через терминал появляется ошибка и (почему-то) делается 3 скриншота экрана:


yura_n


#!/usr/bin/env python
# -*- coding: utf-8 -*-
# RemindMe v1.5 created by Dennis Smal' in 2014 godgrace@mail.ru

from __future__ import print_function

import subprocess
import re
import sys

def replace_all(t, d):
    """Общая функция для подмены переменных"""
    for i, j in d.iteritems():
        t = t.replace(i, j, 1)
    return t

def get_datex(text):
    """Извлекает из текста дату и подстроку с датой, которую нужно удалить"""
    whatdate = ''
    delwhatdate = ''
    datex = re.findall(r'\d{2}[.,-]\d{2}[.,-]\d{4}|\d{1}[.,-]\d{2}[.,-]\d{4}',text) # ищем дату в формате 19.08.2014 или 19-08-2014 или 19,08,2014
    if datex:
        date = datex[0].replace('-','.').replace(',','.') # преобразуем дату в формат 19.08.2014
        whatdate = date
        delwhatdate = datex[0]+' '
    return whatdate, delwhatdate

def get_day(text):
    """Извлекает из текста день недели и подстроку, которую нужно удалить"""
    when = ''
    delday = ''

    day = re.findall('завтра|Завтра|в понедельник|во вторник|в среду|в четверг|в пятницу|в субботу|в воскресенье',text)
    daywithoutin = re.findall('понедельник|вторник|среда|четверг|пятница|суббота|воскресенье',text)
    if day:
        ind = {'завтра':'tomorrow', 'Завтра':'tomorrow', 'в понедельник':'mon', 'во вторник':'tue', 'в среду':'wed', 'в четверг':'thu', 'в пятницу':'fri', 'в субботу':'sat', 'в воскресенье':'sun'}
        when = replace_all(day[0], ind)
        delday = day[0]+' '
    elif daywithoutin:
        ind = {'понедельник':'mon', 'вторник':'tue', 'среда':'wed', 'четверг':'thu', 'пятница':'fri', 'суббота':'sat', 'воскресенье':'sun'}
        when = replace_all(daywithoutin[0], ind)
        delday = daywithoutin[0]+' '
    return (when, delday)

def get_clock(text):
    """Извлекает из текста время и подстроку, которую нужно удалить"""
    how = ''
    delclock = ''
    clock = re.findall('минуты |часа |дня |минуту |часов |день |минут |час |дней ',text)
    if clock: # смотрим, есть ли указание на часы, минуты, дни
        clockbank = {'минут ':'min', 'час ':'hour', 'дней ':'days', 'минуту ':'min', 'часа ':'hours', 'дня ':'days', 'минуты ':'min', 'часов ':'hours', 'день ':'days'}
        how = replace_all(clock[0], clockbank)
        delclock = clock[0]
    return (how, delclock)

def add_task(out, x):
    """Добавляет напоминание в очередь at"""
    #для отладки, чтобы долго не ждать
    #x = 'at now'
    #print (x)
    cmd = 'echo "DISPLAY=:0 ~/remindme/task %s" | %s' % (out, x)
    subprocess.Popen(cmd, shell=True)
   
       
def main(when="Через 15 минут", reminder=""):
    warn_cmd = [
            'zenity',
            '--warning',
            '--text="Попробуйте ещё раз.."'
            ]
    cmd = [
            'zenity',
            '--entry',
            '--title=Напоминалка',
            '--text=Введите напоминание',
            '--entry-text={} {}'.format(when, reminder),
            '--width=400'
            ]

    loop = True
    while loop:
        get = subprocess.check_output(cmd) # получаем текст
        text = get+' ' # добавляем в конец пробел, чтобы отрабатывать уведомления типа "напомнить мне через 10 минут". Если бы пробела не было, параметр clock был бы пуст. В параметре clock после слова "час" тоже стоит пробел, чтобы различать поиск "час" и "часов".
        find = re.findall('ерез [0-9]+|В [0-9:-]+|в [0-9:-]+|ерез час',text)

        if get: # убеждаемся, заполнено ли поле ввода
            if find: # убеждаемся, указано ли время напоминания
                what = find[0].split()
                timex = what[1].replace('-',':').replace('час','1')

                if len(timex) > 2: # заменяет выражения типа "в 10" на "в 10:00"
                    time = timex
                else:
                    time = timex+':00' 
               
                whatdate, delwhatdate = get_datex(text)
                when, delday = get_day(text)
                how, delclock = get_clock(text)

                reps = {'ерез':'at now + %s %s' % (timex,how),'В':'at %s %s %s' % (time,when,whatdate),'в':'at %s %s %s' % (time,when,whatdate)}
                wors = {'Через %s %s' % (what[1],delclock):'','через %s %s' % (what[1],delclock):'','В %s ' % what[1]:'','в %s ' % what[1]:'', '%s' % delday:'', 'Через час':'', 'через час':'', '%s' % delwhatdate:'',} # какие слова мы будем удалять
                x = replace_all(what[0], reps) # это время, на которое запланировано появление напоминания
                out = replace_all(text, wors) # это текст напоминания

                add_task(out, x)
                loop = False

            else:
                error = subprocess.check_output(warn_cmd)
        else:
            loop = False

def usage():
    s = "Использование: {} [Время напоминания [Напоминание]]".format(__file__)
    print(s)

if __name__ == "__main__":
    if len(sys.argv) <= 3:
        main(*sys.argv[1:])
    else:
        usage()

Проблема с табом в одной строке. Остальное проверить не могу пока, времени нет.

sx88

Цитата: yura_n от 12 февраля 2015, 17:56:58Проблема с табом в одной строке.
Хотелось бы верить, что в этом вся проблема. По-видимому, у других пользователей скрипт работает потому как нигде не нашел фразы вроде "а у меня не запускается". Вот и хотелось бы услышать мнение более опытных товарищей.

alsoijw

Почему питонокод запускаешь через sh?
Мало видеть нам начало - надо видеть и конец. Если видишь ты создание - значит где-то есть ТВОРЕЦ
Многие жалуются: геометрия в жизни не пригодилась. Ямб от хорея им приходится отличать ежедневно?

sx88

Скажите как запускать :) Лишь бы работало :P

yura_n

Цитата: sx88 от 12 февраля 2015, 18:34:10По-видимому, у других пользователей скрипт работает потому как нигде не нашел фразы вроде "а у меня не запускается".
Значит вы скопировали его неправильно.

alsoijw

sx88, python имя\ файла если не поможет - выхлоп сюда
yura_n, не обязательно. там на гитхаб даётся ссылка а от туда не правильно скопировать надо суметь.
Мало видеть нам начало - надо видеть и конец. Если видишь ты создание - значит где-то есть ТВОРЕЦ
Многие жалуются: геометрия в жизни не пригодилась. Ямб от хорея им приходится отличать ежедневно?

yura_n

Цитата: alsoijw от 12 февраля 2015, 20:38:30yura_n, не обязательно. там на гитхаб даётся ссылка а от туда не правильно скопировать надо суметь.
alsoijw, тут вариантов немного. Либо он там лежит с ошибкой, либо сюда скопирован неправильно.

    elif daywithoutin:
    ind = {'понедельник':'mon', 'вторник':'tue', 'среда':'wed', 'четверг':'thu', 'пятница':'fri', 'суббота':'sat', 'воскресенье':'sun'}
        when = replace_all(daywithoutin[0], ind)
        delday = daywithoutin[0]+' '
    return (when, delday)

После строки с elif таб обязателен.

sx88

Цитата: yura_n от 12 февраля 2015, 20:41:58После строки с elif таб обязателен.
Да, Вы правы.

Цитата: alsoijw от 12 февраля 2015, 20:38:30если не поможет - выхлоп сюда
Сделал там, как посоветовал youra_n, далее опять ошибка:
sx@light:~/remindme$ python remind.py
Traceback (most recent call last):
  File "remind.py", line 119, in <module>
    main(*sys.argv[1:])
  File "remind.py", line 76, in main
    '--entry-text={} {}'.format(when, reminder),
ValueError: zero length field name in format



Меня интересует вопрос:"Раз уже выложили в официальный источник, как-то тестировали, то почему ж ошибки лезут как тараканы из банки?"

yura_n

Скрипт, очевидно, ждет входного параметра. Попробуйте что-нибудь вроде:

python remind.py что-то_здесь

sx88

sx@light:~/remindme$ python remind.py 19.09.2015
Traceback (most recent call last):
  File "remind.py", line 119, in <module>
    main(*sys.argv[1:])
  File "remind.py", line 76, in main
    '--entry-text={} {}'.format(when, reminder),
ValueError: zero length field name in format
sx@light:~/remindme$ python remind.py task
Traceback (most recent call last):
  File "remind.py", line 119, in <module>
    main(*sys.argv[1:])
  File "remind.py", line 76, in main
    '--entry-text={} {}'.format(when, reminder),
ValueError: zero length field name in format
sx@light:~/remindme$


Leo

Цитата: alsoijw от 12 февраля 2015, 20:00:00Почему питонокод запускаешь через sh?
ну вроде как интерпретатор явно указан в начале скрипта
#!/usr/bin/env python
в свойствах файла должно стоять разрешение на выполнение.

sx88

Цитата: Leo от 12 февраля 2015, 22:05:29в свойствах файла должно стоять разрешение на выполнение.
Стоит  ???
sx@light:~/remindme$ ls -l
итого 16
-rwxr-xr-x 1 sx sx 6091 Фев 12 21:15 remind.py
-rwxr-xr-x 1 sx sx  212 Фев 12 17:23 task


yura_n

#13
Сейчас появилось время разобраться... Не надо этим пользоваться. Такую, блин, околесицу еще надо расстараться выдумать.  ;D Я вообще сильно сомневаюсь, что ЭТО даже у автора работало, ошибка на ошибке.
Поставьте плагин ReminderFox к Thunderbird, получите нормальную запоминалку.

ihammers

Тоже посмотрел код... Исходники брал с GitHub. Отступы, по мне так это ещё маленькая проблема.
На входе он ждёт до 3-х параметров.

  • remind.py
  • when -- когда
  • reminder -- что нужно сделать
На python 3 у меня вылетал почти сразу, а на 2.7 уходил в цикл "Попробуйте ещё раз..."

Для KDE есть kalarm, посмотрите, может понравиться.
Debian GNU/Linux Bookworm, LXQt/OpenBox: AMD Ryzen 5 5600G / 64Gb RAM
_______________________________
Debian GNU/Linux Bookworm, без графики: AMD Phenon X4 / 16Gb RAM
_______________________________
Debian GNU/Linux Bookworm, LXQt/OpenBox: Acer Aspire One 722 AMD C60 / 8Gb RAM / ATI HD6290