Giter Club home page Giter Club logo

knockknock's Introduction

Knock Knock

made-with-python Downloads Downloads GitHub stars

A small library to get a notification when your training is complete or when it crashes during the process with two additional lines of code.

When training deep learning models, it is common to use early stopping. Apart from a rough estimate, it is difficult to predict when the training will finish. Thus, it can be interesting to set up automatic notifications for your training. It is also interesting to be notified when your training crashes in the middle of the process for unexpected reasons.

Installation

Install with pip or equivalent.

pip install knockknock

This code has only been tested with Python >= 3.6.

Usage

The library is designed to be used in a seamless way, with minimal code modification: you only need to add a decorator on top your main function call. The return value (if there is one) is also reported in the notification.

There are currently twelve ways to setup notifications:

Platform External Contributors
email -
Slack -
Telegram -
Microsoft Teams @noklam
Text Message @abhishekkrthakur
Discord @watkinsm
Desktop @atakanyenel @eyalmazuz
Matrix @jcklie
Amazon Chime @prabhakar267
DingTalk @wuutiing
RocketChat @radao
WeChat Work @jcyk

Email

The service relies on Yagmail a GMAIL/SMTP client. You'll need a gmail email address to use it (you can setup one here, it's free). I recommend creating a new one (rather than your usual one) since you'll have to modify the account's security settings to allow the Python library to access it by Turning on less secure apps.

Python

from knockknock import email_sender

@email_sender(recipient_emails=["<[email protected]>", "<[email protected]>"], sender_email="<grandma'[email protected]>")
def train_your_nicest_model(your_nicest_parameters):
    import time
    time.sleep(10000)
    return {'loss': 0.9} # Optional return value

Command-line

knockknock email \
    --recipient-emails <[email protected]>,<[email protected]> \
    --sender-email <grandma'[email protected]> \
    sleep 10

If sender_email is not specified, then the first email in recipient_emails will be used as the sender's email.

Note that launching this will asks you for the sender's email password. It will be safely stored in the system keyring service through the keyring Python library.

Slack

Similarly, you can also use Slack to get notifications. You'll have to get your Slack room webhook URL and optionally your user id (if you want to tag yourself or someone else).

Python

from knockknock import slack_sender

webhook_url = "<webhook_url_to_your_slack_room>"
@slack_sender(webhook_url=webhook_url, channel="<your_favorite_slack_channel>")
def train_your_nicest_model(your_nicest_parameters):
    import time
    time.sleep(10000)
    return {'loss': 0.9} # Optional return value

You can also specify an optional argument to tag specific people: user_mentions=[<your_slack_id>, <grandma's_slack_id>].

Command-line

knockknock slack \
    --webhook-url <webhook_url_to_your_slack_room> \
    --channel <your_favorite_slack_channel> \
    sleep 10

You can also specify an optional argument to tag specific people: --user-mentions <your_slack_id>,<grandma's_slack_id>.

Telegram

You can also use Telegram Messenger to get notifications. You'll first have to create your own notification bot by following the three steps provided by Telegram here and save your API access TOKEN.

Telegram bots are shy and can't send the first message so you'll have to do the first step. By sending the first message, you'll be able to get the chat_id required (identification of your messaging room) by visiting https://api.telegram.org/bot<YourBOTToken>/getUpdates and get the int under the key message['chat']['id'].

Python

from knockknock import telegram_sender

CHAT_ID: int = <your_messaging_room_id>
@telegram_sender(token="<your_api_token>", chat_id=CHAT_ID)
def train_your_nicest_model(your_nicest_parameters):
    import time
    time.sleep(10000)
    return {'loss': 0.9} # Optional return value

Command-line

knockknock telegram \
    --token <your_api_token> \
    --chat-id <your_messaging_room_id> \
    sleep 10

Microsoft Teams

Thanks to @noklam, you can also use Microsoft Teams to get notifications. You'll have to get your Team Channel webhook URL.

Python

from knockknock import teams_sender

@teams_sender(token="<webhook_url_to_your_teams_channel>")
def train_your_nicest_model(your_nicest_parameters):
    import time
    time.sleep(10)
    return {'loss': 0.9} # Optional return value

Command-line

knockknock teams \
    --webhook-url <webhook_url_to_your_teams_channel> \
    sleep 10

You can also specify an optional argument to tag specific people: user_mentions=[<your_teams_id>, <grandma's_teams_id>].

Text Message (SMS)

Thanks to @abhishekkrthakur, you can use Twilio to send text message notifications. You'll have to setup a Twilio account here, which is paid service with competitive prices: for instance in the US, getting a new number and sending one text message through this service respectively cost $1.00 and $0.0075. You'll need to get (a) a phone number, (b) your account SID and (c) your authentification token. Some detail here.

Python

from knockknock import sms_sender

ACCOUNT_SID: str = "<your_account_sid>"
AUTH_TOKEN: str = "<your_auth_token>"
@sms_sender(account_sid=ACCOUNT_SID, auth_token=AUTH_TOKEN, recipient_number="<recipient's_number>", sender_number="<sender's_number>")
def train_your_nicest_model(your_nicest_parameters):
    import time
    time.sleep(10)
    return {'loss': 0.9} # Optional return value

Command-line

knockknock sms \
    --account-sid <your_account_sid> \
    --auth-token <your_account_auth_token> \
    --recipient-number <recipient_number> \
    --sender-number <sender_number>
    sleep 10

Discord

Thanks to @watkinsm, you can also use Discord to get notifications. You'll just have to get your Discord channel's webhook URL.

Python

from knockknock import discord_sender

webhook_url = "<webhook_url_to_your_discord_channel>"
@discord_sender(webhook_url=webhook_url)
def train_your_nicest_model(your_nicest_parameters):
    import time
    time.sleep(10000)
    return {'loss': 0.9} # Optional return value

Command-line

knockknock discord \
    --webhook-url <webhook_url_to_your_discord_channel> \
    sleep 10

Desktop Notification

You can also get notified from a desktop notification. It is currently only available for MacOS and Linux and Windows 10. For Linux it uses the nofity-send command which uses libnotify, In order to use libnotify, you have to install a notification server. Cinnamon, Deepin, Enlightenment, GNOME, GNOME Flashback and KDE Plasma use their own implementations to display notifications. In other desktop environments, the notification server needs to be launched using your WM's/DE's "autostart" option.

Python

from knockknock import desktop_sender

@desktop_sender(title="Knockknock Desktop Notifier")
def train_your_nicest_model(your_nicest_parameters):
    import time
    time.sleep(10000)
    return {"loss": 0.9}

Command Line

knockknock desktop \
    --title 'Knockknock Desktop Notifier' \
    sleep 2

Matrix

Thanks to @jcklie, you can send notifications via Matrix. The homeserver is the server on which your user that will send messages is registered. Do not forget the schema for the URL (http or https). You'll have to get the access token for a bot or your own user. The easiest way to obtain it is to look into Riot looking in the riot settings, Help & About, down the bottom is: Access Token:<click to reveal>. You also need to specify a room alias to which messages are sent. To obtain the alias in Riot, create a room you want to use, then open the room settings under Room Addresses and add an alias.

Python

from knockknock import matrix_sender

HOMESERVER = "<url_to_your_home_server>" # e.g. https://matrix.org
TOKEN = "<your_auth_token>"              # e.g. WiTyGizlr8ntvBXdFfZLctyY
ROOM = "<room_alias"                     # e.g. #knockknock:matrix.org

@matrix_sender(homeserver=HOMESERVER, token=TOKEN, room=ROOM)
def train_your_nicest_model(your_nicest_parameters):
    import time
    time.sleep(10000)
    return {'loss': 0.9} # Optional return value

Command-line

knockknock matrix \
    --homeserver <homeserver> \
    --token <token> \
    --room <room> \
    sleep 10

Amazon Chime

Thanks to @prabhakar267, you can also use Amazon Chime to get notifications. You'll have to get your Chime room webhook URL.

Python

from knockknock import chime_sender

@chime_sender(webhook_url="<webhook_url_to_your_chime_room>")
def train_your_nicest_model(your_nicest_parameters):
    import time
    time.sleep(10)
    return {'loss': 0.9} # Optional return value

Command-line

knockknock chime \
    --webhook-url <webhook_url_to_your_chime_room> \
    sleep 10

You can also specify an optional argument to tag specific people: user_mentions=[<your_alias>, <grandma's_alias>].

DingTalk

DingTalk is now supported thanks to @wuutiing. Given DingTalk chatroom robot's webhook url and secret/keywords(at least one of them are set when creating a chatroom robot), your notifications will be sent to reach any one in that chatroom.

Python

from knockknock import dingtalk_sender

webhook_url = "<webhook_url_to_your_dingtalk_chatroom_robot>"
@dingtalk_sender(webhook_url=webhook_url, secret="<your_robot_secret_if_set>", keywords=["<list_of_keywords_if_set>"])
def train_your_nicest_model(your_nicest_parameters):
    import time
    time.sleep(10000)
    return {'loss': 0.9} # Optional return value

Command-line

knockknock dingtalk \
    --webhook-url <webhook_url_to_your_dingtalk_chatroom_robot> \
    --secret <your_robot_secret_if_set> \
    sleep 10

You can also specify an optional argument to at specific people: user_mentions=["<list_of_phonenumbers_who_you_want_to_tag>"].

RocketChat

You can use RocketChat to get notifications. You'll need the following before you can post notifications:

  • a RocketChat server e.g. rocketchat.yourcompany.com
  • a RocketChat user id (you'll be able to view your user id when you create a personal access token in the next step)
  • a RocketChat personal access token (create one as per this guide)
  • a RocketChat channel

Python

from knockknock import rocketchat_sender

@rocketchat_sender(
    rocketchat_server_url="<url_to_your_rocketchat_server>",
    rocketchat_user_id="<your_rocketchat_user_id>",
    rocketchat_auth_token="<your_rocketchat_auth_token>",
    channel="<channel_name>")
def train_your_nicest_model(your_nicest_parameters):
    import time
    time.sleep(10000)
    return {'loss': 0.9} # Optional return value

You can also specify two optional arguments:

  • to tag specific users: user_mentions=[<your_user_name>, <grandma's_user_name>]
  • to use an alias for the notification: alias="My Alias"

Command-line

knockknock rocketchat \
    --rocketchat-server-url <url_to_your_rocketchat_server> \
    --rocketchat-user-id <your_rocketchat_user_id> \
    --rocketchat-auth-token <your_rocketchat_auth_token> \
    --channel <channel_name> \
    sleep 10

WeChat Work

WeChat Work is now supported thanks to @jcyk. Given WeChat Work chatroom robot's webhook url, your notifications will be sent to reach anyone in that chatroom.

Python

from knockknock import wechat_sender

webhook_url = "<webhook_url_to_your_wechat_work_chatroom_robot>"
@wechat_sender(webhook_url=webhook_url)
def train_your_nicest_model(your_nicest_parameters):
    import time
    time.sleep(10000)
    return {'loss': 0.9} # Optional return value

Command-line

knockknock wechat \
    --webhook-url <webhook_url_to_your_wechat_work_chatroom_robot> \
    sleep 10

You can also specify an optional argument to tag specific people: user-mentions=["<list_of_userids_you_want_to_tag>"] and/or user-mentions-mobile=["<list_of_phonenumbers_you_want_to_tag>"].

Note on distributed training

When using distributed training, a GPU is bound to its process using the local rank variable. Since knockknock works at the process level, if you are using 8 GPUs, you would get 8 notifications at the beginning and 8 notifications at the end... To circumvent that, except for errors, only the master process is allowed to send notifications so that you receive only one notification at the beginning and one notification at the end.

Note: In PyTorch, the launch of torch.distributed.launch sets up a RANK environment variable for each process (see here). This is used to detect the master process, and for now, the only simple way I came up with. Unfortunately, this is not intended to be general for all platforms but I would happily discuss smarter/better ways to handle distributed training in an issue/PR.

knockknock's People

Contributors

abhishekkrthakur avatar alxwrd avatar atakanyenel avatar christophalt avatar dylanjcastillo avatar eyalmazuz avatar jcklie avatar jcyk avatar prabhakar267 avatar radao avatar rish-16 avatar shauryauppal-1mg avatar sshleifer avatar victorsanh avatar wuutiing avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

knockknock's Issues

Timeout

Hello,
Thank you for creating this project for getting notified. This works well on my laptop but when I try to get notified when my code runs on jupyter via email, this problem happened.

~/.local/lib/python3.7/site-packages/knockknock/email_sender.py in wrapper_sender(*args, **kwargs)
51 for i in range(len(recipient_emails)):
52 current_recipient = recipient_emails[i]
---> 53 yag_sender.send(current_recipient, 'Training has started 🎬', contents)
54 try:
55 value = func(*args, **kwargs)

~/.local/lib/python3.7/site-packages/yagmail/sender.py in send(self, to, subject, contents, attachments, cc, bcc, preview_only, headers, prettify_html, message_id, group_messages)
151 ):
152 """ Use this to send an email with gmail"""
--> 153 self.login()
154 recipients, msg_string = self.prepare_send(
155 to,

~/.local/lib/python3.7/site-packages/yagmail/sender.py in login(self)
204 self._login_oauth2(self.credentials)
205 else:
--> 206 self._login(self.credentials)
207
208 def _login(self, password):

~/.local/lib/python3.7/site-packages/yagmail/sender.py in _login(self, password)
211 connection to the SMTP server was closed by the user.
212 """
--> 213 self.smtp = self.connection(self.host, self.port, **self.kwargs)
214 self.smtp.set_debuglevel(self.debuglevel)
215 if self.starttls:

/opt/tljh/user/lib/python3.7/smtplib.py in init(self, host, port, local_hostname, keyfile, certfile, timeout, source_address, context)
1029 self.context = context
1030 SMTP.init(self, host, port, local_hostname, timeout,
-> 1031 source_address)
1032
1033 def _get_socket(self, host, port, timeout):

/opt/tljh/user/lib/python3.7/smtplib.py in init(self, host, port, local_hostname, timeout, source_address)
249
250 if host:
--> 251 (code, msg) = self.connect(host, port)
252 if code != 220:
253 self.close()

/opt/tljh/user/lib/python3.7/smtplib.py in connect(self, host, port, source_address)
334 if self.debuglevel > 0:
335 self._print_debug('connect:', (host, port))
--> 336 self.sock = self._get_socket(host, port, self.timeout)
337 self.file = None
338 (code, msg) = self.getreply()

/opt/tljh/user/lib/python3.7/smtplib.py in _get_socket(self, host, port, timeout)
1035 self._print_debug('connect:', (host, port))
1036 new_socket = socket.create_connection((host, port), timeout,
-> 1037 self.source_address)
1038 new_socket = self.context.wrap_socket(new_socket,
1039 server_hostname=self._host)

/opt/tljh/user/lib/python3.7/socket.py in create_connection(address, timeout, source_address)
726 if err is not None:
727 try:
--> 728 raise err
729 finally:
730 # Break explicitly a reference cycle

/opt/tljh/user/lib/python3.7/socket.py in create_connection(address, timeout, source_address)
714 if source_address:
715 sock.bind(source_address)
--> 716 sock.connect(sa)
717 # Break explicitly a reference cycle
718 err = None

I turned my new backup google account' safety option off as instruction offered on https://pypi.org/project/knockknock/ but this happened and search on this issue has no results, so here it goes.

My recipants_emails is firstly set to my private email which is not of gmail, after error above occured, I changed it to my previous google account and this time keyrings.alt dependency is needed but enve if this is satisfied the error occured again. Now I'm helpless.
Can anyone explain why this happened and how can I solve it?
Much thanks!

disable slack_sender during unittests

Is there a way to temporarily disable slack sender during unittests?
I want to add knock knock to my training code but don't want it to slack me every time I run the tests.

[AWS EC2] RuntimeError: No recommended backend was available

In an AWS EC2 instance with the Deep Learning AMI installed, I first did source activate pytorch_p36 to activate that particular pre-built environment by AWS. Next, I did pip install knockknock. This was successful.

I created an appropriate Gmail account to send notifications, and then I created a script called testing_kk.py which contains the following code (removed the email addresses for privacy):

from knockknock import email_sender

@email_sender(recipient_email="<my email address>", sender_email="<sender email address>")
def train_your_nicest_model(your_nicest_parameters):
    return {'loss': 0.9} # Optional return value

if __name__ == "__main__":
    train_your_nicest_model(1)

When I run the above code in the same environment, I get the following stack-trace:

Traceback (most recent call last):
  File "testing_kk.py", line 8, in <module>
    train_your_nicest_model(1)
  File "/home/ec2-user/anaconda3/envs/pytorch_p36/lib/python3.6/site-packages/knockknock/email_sender.py", line 50, in wrapper_sender
    yag_sender.send(recipient_email, 'Training has started 🎬', contents)
  File "/home/ec2-user/anaconda3/envs/pytorch_p36/lib/python3.6/site-packages/yagmail/sender.py", line 147, in send
    self.login()
  File "/home/ec2-user/anaconda3/envs/pytorch_p36/lib/python3.6/site-packages/yagmail/sender.py", line 246, in login
    self._login(self.credentials)
  File "/home/ec2-user/anaconda3/envs/pytorch_p36/lib/python3.6/site-packages/yagmail/sender.py", line 203, in _login
    password = self.handle_password(self.user, password)
  File "/home/ec2-user/anaconda3/envs/pytorch_p36/lib/python3.6/site-packages/yagmail/sender.py", line 209, in handle_password
    return handle_password(user, password)
  File "/home/ec2-user/anaconda3/envs/pytorch_p36/lib/python3.6/site-packages/yagmail/password.py", line 11, in handle_password
    password = keyring.get_password("yagmail", user)
  File "/home/ec2-user/anaconda3/envs/pytorch_p36/lib/python3.6/site-packages/keyring/core.py", line 55, in get_password
    return _keyring_backend.get_password(service_name, username)
  File "/home/ec2-user/anaconda3/envs/pytorch_p36/lib/python3.6/site-packages/keyring/backends/fail.py", line 24, in get_password
    raise RuntimeError(msg)
RuntimeError: No recommended backend was available. Install a recommended 3rd party backend package; or, install the keyrings.alt package if you want to use the non-recommended backends. See https://pypi.org/project/keyring for details.

From the README, it sounded like running this script would ask me for the sender email password upon the first run and consequently it would be stored in the system keyring service for future runs. But that didn't seem to happen above.

I tried running pip install keyring and it seems to have been installed already, so I'm unsure why it says the backend was unavailable at run-time. Any ideas?

ConnectionResetError: [Errno 54] Connection reset by peer

Hey, I have been trying to use the email functionality of knock-knock but I m facing this error. Could you please help me with this?
Sharing the code and error below.

Thanks!
Bhavishya

CODE

imports..

def train_model(X_train,y_train,X_test,y_test):
    classifier=SVC()
    classifier.fit(X_train,y_train)
    return f'Accuracy of the model: {(classifier.score(X_test, y_test))*100}%'

@email_sender(recipient_emails=["[email protected]"],sender_email="[email protected]")
def train_model_email_notify(X_train, y_train, X_test, y_test):
    return train_model(X_train,
                       y_train,
                       X_test,
                       y_test)


wines=datasets.load_wine()
x = wines['data']
y = wines['target']


X_train, X_test, y_train, y_test = train_test_split(x,y,test_size=0.2)
mm = MinMaxScaler()
X_train=mm.fit_transform(X_train)
X_test=mm.fit_transform(X_test)
train_model_email_notify(X_train, y_train, X_test, y_test)

ERROR

Traceback (most recent call last):
  File "/Users/bhavishya.pandit/PycharmProjects/ProjectTesting/test.py", line 30, in <module>
    train_model_email_notify(X_train, y_train, X_test, y_test)
  File "/Library/Python/3.8/site-packages/knockknock/email_sender.py", line 53, in wrapper_sender
    yag_sender.send(current_recipient, 'Training has started 🎬', contents)
  File "/Library/Python/3.8/site-packages/yagmail/sender.py", line 156, in send
    self.login()
  File "/Library/Python/3.8/site-packages/yagmail/sender.py", line 210, in login
    self._login(self.credentials)
  File "/Library/Python/3.8/site-packages/yagmail/sender.py", line 217, in _login
    self.smtp = self.connection(self.host, self.port, **self.kwargs)
  File "/Library/Developer/CommandLineTools/Library/Frameworks/Python3.framework/Versions/3.8/lib/python3.8/smtplib.py", line 1034, in __init__
    SMTP.__init__(self, host, port, local_hostname, timeout,
  File "/Library/Developer/CommandLineTools/Library/Frameworks/Python3.framework/Versions/3.8/lib/python3.8/smtplib.py", line 253, in __init__
    (code, msg) = self.connect(host, port)
  File "/Library/Developer/CommandLineTools/Library/Frameworks/Python3.framework/Versions/3.8/lib/python3.8/smtplib.py", line 339, in connect
    self.sock = self._get_socket(host, port, self.timeout)
  File "/Library/Developer/CommandLineTools/Library/Frameworks/Python3.framework/Versions/3.8/lib/python3.8/smtplib.py", line 1042, in _get_socket
    new_socket = self.context.wrap_socket(new_socket,
  File "/Library/Developer/CommandLineTools/Library/Frameworks/Python3.framework/Versions/3.8/lib/python3.8/ssl.py", line 500, in wrap_socket
    return self.sslsocket_class._create(
  File "/Library/Developer/CommandLineTools/Library/Frameworks/Python3.framework/Versions/3.8/lib/python3.8/ssl.py", line 1040, in _create
    self.do_handshake()
  File "/Library/Developer/CommandLineTools/Library/Frameworks/Python3.framework/Versions/3.8/lib/python3.8/ssl.py", line 1309, in do_handshake
    self._sslobj.do_handshake()
ConnectionResetError: [Errno 54] Connection reset by peer

Windows desktop notification not displaying entire message content

So looking at the code you'd expect the entire message to be displayed on the Windows notification when the model trains successfully:

if master_process:
end_time = datetime.datetime.now()
elapsed_time = end_time - start_time
contents = ["Your training is complete 🎉",
'Machine name: %s' % host_name,
'Main call: %s' % func_name,
'Starting date: %s' % start_time.strftime(DATE_FORMAT),
'End date: %s' % end_time.strftime(DATE_FORMAT),
'Training duration: %s' % str(elapsed_time)]
try:
str_value = str(value)
contents.append('Main call returned value: %s'% str_value)
except:
contents.append('Main call returned value: %s'% "ERROR - Couldn't str the returned value.")
text = '\n'.join(contents)
show_notification(text, title)

However since win10toast sets the height and width to the default size, if the text is too long it will be truncated and not fully displayed:

self.hwnd = CreateWindow(self.classAtom, "Taskbar", style,
                                 0, 0, CW_USEDEFAULT,
                                 CW_USEDEFAULT,
                                 0, 0, self.hinst, None)

Running a test code for it produced the following even when expanded the notification:

@desktop_sender(title="test")
def train():
    import time
    time.sleep(1)
    return {"loss":1}

image

So the end date, training duration and the dictionary returned from the train() function were not displayed.

It would be great if there was a more responsive design to the size of the notification, but I believe that the CreateWindow used in win10toast only expects fixed sizes, so I'm not sure how to resolve this issue. I even tried to change the width and height to no avail.

When the function finished, it still need the password?

As the figure below, it needs the password when we start the work, it is ok cause we are on the computer now. But when the work finished, it still needs the password, we want to use this lib for convenient if we can't keep eyes on the computer, but as far, it can't solve the problem?
image

Need a CONTRIBUTING.md. (Trouble setting up repository in Mac OS)

I am trying to set up the repository locally on my machine (Mac OS) with virtual env and Python 3.7 but ran into an issue while trying to install 'win10toast==0.9'.

I tried using pip3 install 'win10toast==0.9'

Received this as an error:

WARNING: pip is being invoked by an old script wrapper. This will fail in a future version of pip.
Please see https://github.com/pypa/pip/issues/5599 for advice on fixing the underlying issue.
To avoid this problem you can invoke Python with '-m pip' instead of running pip directly.
Defaulting to user installation because normal site-packages is not writeable
Collecting win10toast==0.9
  Using cached win10toast-0.9-py2.py3-none-any.whl (21 kB)
Requirement already satisfied: setuptools in /Library/Developer/CommandLineTools/Library/Frameworks/Python3.framework/Versions/3.7/lib/python3.7/site-packages (from win10toast==0.9) (40.8.0)
Collecting pypiwin32
  Using cached pypiwin32-223-py3-none-any.whl (1.7 kB)
ERROR: Could not find a version that satisfies the requirement pywin32>=223 (from pypiwin32->win10toast==0.9) (from versions: none)
ERROR: No matching distribution found for pywin32>=223 (from pypiwin32->win10toast==0.9)

Quick google searches suggested installing pypiwin32/pywin32, but they did not do the trick :( Any quick pointers?

Maybe worth putting together a setup or contributing guide for the repo?

Allow sending custom message

knockknock can be a great general purpose library to send messages to different messaging clients. Why restrict it to just sending messages about training completion.

Telegram crashes tensorflow model

Hello,
I recently installed knockknock and I am using it with the telegram functionality. It works and sends me messages, however when my tensorflow model is done training, knockknock crashes the entire process with the below error (taken from the telegram message received):

Your training has crashed ☠️
Machine name: TomasPC
Main call: auto_train_ML_model
Starting date: 2020-07-10 23:32:02
Crash date: 2020-07-10 23:51:43
Crashed training duration: 0:19:40.329927


Here's the error:
nan


Traceback:
Traceback (most recent call last):
  File "D:\Anaconda\envs\tf-gpu\lib\site-packages\knockknock\telegram_sender.py", line 55, in wrapper_sender
    value = func(*args, **kwargs)
  File "d:\AutoKerasProject\AutoKeras. AutoModel. Time Series. Timeseriesgenerator.py", line 125, in auto_train_ML_model
    print(y_train)
  File "D:\Anaconda\envs\tf-gpu\lib\site-packages\autokeras\auto_model.py", line 444, in evaluate
    dataset = self._process_xy(x, y, False)
  File "D:\Anaconda\envs\tf-gpu\lib\site-packages\autokeras\auto_model.py", line 307, in _process_xy
    y = self._adapt(y, fit, self._heads, self._output_adapters)
  File "D:\Anaconda\envs\tf-gpu\lib\site-packages\autokeras\auto_model.py", line 275, in _adapt
    source = adapter.transform(source)
  File "D:\Anaconda\envs\tf-gpu\lib\site-packages\autokeras\engine\adapter.py", line 88, in transform
    return self.convert_to_dataset(dataset)
  File "D:\Anaconda\envs\tf-gpu\lib\site-packages\autokeras\adapters\output_adapter.py", line 101, in convert_to_dataset
    dataset = self.label_encoder.encode(dataset)
  File "D:\Anaconda\envs\tf-gpu\lib\site-packages\autokeras\encoders.py", line 128, in encode
    data))).reshape(-1, 1)
  File "D:\Anaconda\envs\tf-gpu\lib\site-packages\autokeras\encoders.py", line 127, in <lambda>
    return np.array(list(map(lambda x: self._label_to_int[x],
KeyError: nan

keyring.errors.NoKeyringError: No recommended backend was available. Install a recommended 3rd party backend package; or, install the keyrings.alt package if you want to use the non-recommended backends

Execution:

knockknock email --recipient-emails [email protected] --sender-email [email protected] sleep 10

Full error message:

Traceback (most recent call last):
  File "/home/jovyan/conda/dsEnv/bin/knockknock", line 10, in <module>
    sys.exit(main())
  File "/home/jovyan/conda/dsEnv/lib/python3.8/site-packages/knockknock/__main__.py", line 207, in main
    sender_func(**args)(run_func)()
  File "/home/jovyan/conda/dsEnv/lib/python3.8/site-packages/knockknock/email_sender.py", line 53, in wrapper_sender
    yag_sender.send(current_recipient, 'Training has started 🎬', contents)
  File "/home/jovyan/conda/dsEnv/lib/python3.8/site-packages/yagmail/sender.py", line 153, in send
    self.login()
  File "/home/jovyan/conda/dsEnv/lib/python3.8/site-packages/yagmail/sender.py", line 206, in login
    self._login(self.credentials)
  File "/home/jovyan/conda/dsEnv/lib/python3.8/site-packages/yagmail/sender.py", line 224, in _login
    password = self.handle_password(self.user, password)
  File "/home/jovyan/conda/dsEnv/lib/python3.8/site-packages/yagmail/sender.py", line 230, in handle_password
    return handle_password(user, password)
  File "/home/jovyan/conda/dsEnv/lib/python3.8/site-packages/yagmail/password.py", line 11, in handle_password
    password = keyring.get_password("yagmail", user)
  File "/home/jovyan/conda/dsEnv/lib/python3.8/site-packages/keyring/core.py", line 55, in get_password
    return get_keyring().get_password(service_name, username)
  File "/home/jovyan/conda/dsEnv/lib/python3.8/site-packages/keyring/backends/fail.py", line 25, in get_password
    raise NoKeyringError(msg)
keyring.errors.NoKeyringError: No recommended backend was available. Install a recommended 3rd party backend package; or, i
nstall the keyrings.alt package if you want to use the non-recommended backends. See https://pypi.org/project/keyring for d
etails.

I didn't find https://pypi.org/project/keyring helpful. Installing dbus-python didn't change the behavior and it's unclear which username and password keyrings is looking for. Are we talking email credentials username and password? What if you wanted to use a different knockknock service like Slack, would the keyrings username and password credentials specified need to be different?

Does not work when running code remotely

I am running my code through SSH. My connecting device is a Windows 10 computer, and the machine actually doing the training is a linux server. When I use knockknock, though, I get the following trace.

Traceback (most recent call last):
  File "/home/bram/.local/share/virtualenvs/predicting-syntactic-equivalence-g0sIkWgJ/lib/python3.7/site-packages/secretstorage/util.py", line 47, in send_and_get_reply
    return self._connection.send_and_get_reply(msg)
  File "/home/bram/.local/share/virtualenvs/predicting-syntactic-equivalence-g0sIkWgJ/lib/python3.7/site-packages/jeepney/integrate/blocking.py", line 69, in send_and_get_reply
    return future.result()
  File "/home/bram/.local/share/virtualenvs/predicting-syntactic-equivalence-g0sIkWgJ/lib/python3.7/site-packages/jeepney/integrate/blocking.py", line 31, in result
    raise value
jeepney.wrappers.DBusErrorResponse: [org.freedesktop.DBus.Error.UnknownMethod] ("No such interface 'org.freedesktop.DBus.Properties' on object at path /org/freedesktop/secrets/collection/login",)

The above exception was the direct cause of the following exception:

Traceback (most recent call last):
  File "/home/bram/.local/share/virtualenvs/predicting-syntactic-equivalence-g0sIkWgJ/lib/python3.7/site-packages/secretstorage/collection.py", line 161, in get_default_collection
    return Collection(connection)
  File "/home/bram/.local/share/virtualenvs/predicting-syntactic-equivalence-g0sIkWgJ/lib/python3.7/site-packages/secretstorage/collection.py", line 44, in __init__
    self._collection.get_property('Label')
  File "/home/bram/.local/share/virtualenvs/predicting-syntactic-equivalence-g0sIkWgJ/lib/python3.7/site-packages/secretstorage/util.py", line 65, in get_property
    (signature, value), = self.send_and_get_reply(msg)
  File "/home/bram/.local/share/virtualenvs/predicting-syntactic-equivalence-g0sIkWgJ/lib/python3.7/site-packages/secretstorage/util.py", line 50, in send_and_get_reply
    raise ItemNotFoundException('Item does not exist!') from resp
secretstorage.exceptions.ItemNotFoundException: Item does not exist!

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "/home/bram/.local/share/virtualenvs/predicting-syntactic-equivalence-g0sIkWgJ/lib/python3.7/site-packages/keyring/backends/SecretService.py", line 55, in get_preferred_collection
    collection = secretstorage.get_default_collection(bus)
  File "/home/bram/.local/share/virtualenvs/predicting-syntactic-equivalence-g0sIkWgJ/lib/python3.7/site-packages/secretstorage/collection.py", line 164, in get_default_collection
    'default', session)
  File "/home/bram/.local/share/virtualenvs/predicting-syntactic-equivalence-g0sIkWgJ/lib/python3.7/site-packages/secretstorage/collection.py", line 145, in create_collection
    raise PromptDismissedException('Prompt dismissed.')
secretstorage.exceptions.PromptDismissedException: Prompt dismissed.

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "ml_s2v.py", line 173, in <module>
    trainer.train_model(options)
  File "/home/bram/.local/share/virtualenvs/predicting-syntactic-equivalence-g0sIkWgJ/lib/python3.7/site-packages/knockknock/email_sender.py", line 50, in wrapper_sender
    yag_sender.send(recipient_email, 'Training has started 🎬', contents)
  File "/home/bram/.local/share/virtualenvs/predicting-syntactic-equivalence-g0sIkWgJ/lib/python3.7/site-packages/yagmail/sender.py", line 147, in send
    self.login()
  File "/home/bram/.local/share/virtualenvs/predicting-syntactic-equivalence-g0sIkWgJ/lib/python3.7/site-packages/yagmail/sender.py", line 246, in login
    self._login(self.credentials)
  File "/home/bram/.local/share/virtualenvs/predicting-syntactic-equivalence-g0sIkWgJ/lib/python3.7/site-packages/yagmail/sender.py", line 203, in _login
    password = self.handle_password(self.user, password)
  File "/home/bram/.local/share/virtualenvs/predicting-syntactic-equivalence-g0sIkWgJ/lib/python3.7/site-packages/yagmail/sender.py", line 209, in handle_password
    return handle_password(user, password)
  File "/home/bram/.local/share/virtualenvs/predicting-syntactic-equivalence-g0sIkWgJ/lib/python3.7/site-packages/yagmail/password.py", line 11, in handle_password
    password = keyring.get_password("yagmail", user)
  File "/home/bram/.local/share/virtualenvs/predicting-syntactic-equivalence-g0sIkWgJ/lib/python3.7/site-packages/keyring/core.py", line 55, in get_password
    return _keyring_backend.get_password(service_name, username)
  File "/home/bram/.local/share/virtualenvs/predicting-syntactic-equivalence-g0sIkWgJ/lib/python3.7/site-packages/keyring/backends/SecretService.py", line 67, in get_password
    collection = self.get_preferred_collection()
  File "/home/bram/.local/share/virtualenvs/predicting-syntactic-equivalence-g0sIkWgJ/lib/python3.7/site-packages/keyring/backends/SecretService.py", line 57, in get_preferred_collection
    raise InitError("Failed to create the collection: %s." % e)
keyring.errors.InitError: Failed to create the collection: Prompt dismissed..

It states "Item does not exist" but I'm not sure which item it's referring to. This happens as soon as I launch the code, so I haven't been prompted for a password. In fact, it seems that the prompt is where things go wrong.

[Slack sender] The channel argument is redundant with the webhook_url argument

First of all thanks for the work !

It seems the channel argument is redundant with the webhook_url argument since the creation of a Slack webhook URL requires a channel : the information of the channel is included in the webhook

TODO :

  • remove the argument channel, to avoid breaking change it can set to optional argument instead
  • update the slack section of the README.md

@VictorSanh if you are OK with this, I can do the pull request

Adding a desktop notification for macos

Hello , I was thinking about adding desktop notification. You know the ones that pop up on upper right corner. I have a Mac but it can be extended by others with different OS's. It doesn't require any token info, maybe couple of configuration arguments , and can simply be called with @desktop_sender().

It's not a hard task, there are already libraries for it , but nevertheless I would like to make the PR myself.

What do you think ?

Dependency will cause jupyter notebook to crash

In case of anyone who bump into this problem.

/Users/tnlin/anaconda3/lib/python3.6/site-packages/notebook/base/zmqhandlers.py:284: RuntimeWarning: coroutine 'WebSocketHandler.get' was never awaited
  super(AuthenticatedZMQStreamHandler, self).get(*args, **kwargs)
[W 11:53:18.115 NotebookApp] Replacing stale connection: e1c43480-dd1f-4837-b57d-197e2e20fdb9:24e703ae04c9484c896ecbd5c506b419

My jupyter notebook fail to connect the kernel after install the dependency tornado-6.0.3
I solve the issue by downgrading it: pip install tornado==5.1.1

For for details, see: jupyter/notebook#4437

Here are my dependencies:

Python 3.6.9
jupyter==1.0.0
jupyter-client==5.2.3
jupyter-console==6.0.0
jupyter-contrib-core==0.3.3
jupyter-contrib-nbextensions==0.4.0
jupyter-core==4.4.0
jupyter-highlight-selected-word==0.1.0
jupyter-latex-envs==1.4.6
jupyter-nbextensions-configurator==0.4.0
jupyterlab==0.32.1
jupyterlab-launcher==0.10.5
jupyterthemes==0.18.9
notebook==5.5.0

Update PyPi version to 0.1.8.1

Thank you for keeping up the good work on creating and maintaining this project!

I can see that the version on the repo has updated to 0.1.8.1, can the same be pushed to PyPi?

Thanks!

Is there a proxy method?

Because of my specific network environment, I have to use a proxy to access the internet. I haven't see any method in this project. Can you give me some advice? Thanks!

Consider broadening scope

I've found this library very useful for things aside from just model training. Really it can be used for any python script that is being deployed to cloud infrastructure. I've found it particularly useful for deploying containerised applications which gives me peace of mind that I'll just get a slack message if something has gone wrong. Whether or not it's ML related.

So on that note, I wonder if you would consider broadening the scope of the library to also accommodate other types of script. As far as I can tell, this just means modifying some of the messages to be more generic instead of referring specifically to "training". Potentially there could even be different categories of deployment corresponding to different vocabulary for the messages.

Is this something you would consider? Or maybe there is another library to use in these non-ML circumstances that you're aware of?

Add QPush

Hi, your package is really good! Besides, I think QPush is also worth trying!

socket.gaierror: [Errno -3] Temporary failure in name resolution

Hi there,

When I used the email sender example like below:

from knockknock import email_sender

@email_sender(recipient_email="<[email protected]>", sender_email="<grandma'[email protected]>")
def train_your_nicest_model(your_nicest_parameters):
    import time
    time.sleep(10000)
    return {'loss': 0.9} # Optional return value

I got below error:

socket.gaierror: [Errno -3] Temporary failure in name resolution

Any suggestion for this problem?

Thanks

Refactoring

Some refactoring possible since a lot of code is shared (slack, discord, teams, chime,.. for instance).
Low priority for now.

Showing more details about training.

Hello, sometimes I not only want to know when is the training finished, but also want to know what the result is (training loss, accuracy, F1-score, etc.). Is it possible to show these in email? It may work like this:

  1. the training function is called
  2. the training function successfully finish and return a dict like
{
   loss:0.1,
   acc: 90,
   F1: 89
}
  1. the decorator walk through the returned dict and report the result in the email.

If this sound reasonable to you I may provide a PR later.

Thanks!

Send log messages

I think it would be great if knockknock would also send log messages at a particular configurable level (e.g. error/critical by default). Often you may want to be notified in real time of a particular state but one which does not error out.

Add Gchat

You can make Bots for Google Chat, having that too would be awesome!

installation from conda

since I am using conda to manage my python package, could you please make it available to install this package using conda?

Typo on Microsoft Teams example

Hey,

I found a small typo:

from knockknock import telegram_sender # <-- should be teams_sender

CHAT_ID: int = <your_messaging_room_id>
@teams_sender(token="<webhook_url_to_your_teams_channel>")
...

Is there a functionality to report epoch wise loss and other metrics?

Is there a functionality to report epoch wise loss and other metrics? I am only able to get final losses and metrics but not epoch-wise updates. Can it be done via this library? I want to track the updates of model when I am away from my terminal and compute is not really affordable for me.

Example on Teams is wrong

Your example on teams looks like this:
@teams_sender(token="<webhook_url_to_your_teams_channel>")

while it should look like that:

@teams_sender(webhook_url="<webhook_url_to_your_teams_channel>")

add Wechat Work support

Hi, a lot of users in China are using Wechat Work in their daily work/life. I think many of them would like knockknock to support Wechat Work as well. this PR #47 is an attempt for addressing it. Please consider merge it!

SMS integration

Any plans to add sms notification feature with Twilio API? I can make a PR if it will be added.

platform compatibility bug

when install through pip

pip install knockknock

the requirements win10toast is not available on mac os.

Collecting win10toast==0.0.9
  ERROR: Could not find a version that satisfies the requirement win10toast==0.0.9 (from versions: 0.2, 0.8, 0.9)
ERROR: No matching distribution found for win10toast==0.0.9

suggest distinguishing different platform.

Add matrix

We are using Matrix Chat in our department and it would be nice to add support for it. It gets more and more traction. I will send a pull request for it soonish.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.