Trigger an event when clipboard content changes

Have you thought about using an endless loop and “sleeping” between tries?
I used pyperclip for a simple PoC and it worked like a charm, and Windows and Linux.

import time
import sys
import os

import pyperclip

recent_value = ""
while True:
    tmp_value = pyperclip.paste()
    if tmp_value != recent_value:
        recent_value = tmp_value
        print("Value changed: %s" % str(recent_value)[:20])
    time.sleep(0.1)

Instead of the print, do whatever you want.


Here is a complete multithreading example.

import time
import threading

import pyperclip

def is_url_but_not_bitly(url):
    if url.startswith("http://") and not "bit.ly" in url:
        return True
    return False

def print_to_stdout(clipboard_content):
    print ("Found url: %s" % str(clipboard_content))

class ClipboardWatcher(threading.Thread):
    def __init__(self, predicate, callback, pause=5.):
        super(ClipboardWatcher, self).__init__()
        self._predicate = predicate
        self._callback = callback
        self._pause = pause
        self._stopping = False
            
    def run(self):       
        recent_value = ""
        while not self._stopping:
            tmp_value = pyperclip.paste()
            if tmp_value != recent_value:
                recent_value = tmp_value
                if self._predicate(recent_value):
                    self._callback(recent_value)
            time.sleep(self._pause)
    
    def stop(self):
        self._stopping = True

def main():
    watcher = ClipboardWatcher(is_url_but_not_bitly, 
                               print_to_stdout,
                               5.)
    watcher.start()
    while True:
        try:
            print("Waiting for changed clipboard...")
            time.sleep(10)
        except KeyboardInterrupt:
            watcher.stop()
            break
    

if __name__ == "__main__":
    main()

I create a subclass of threading.Thread, override the methods run and __init__ and create an instance of this class. By calling watcher.start() (not run()!), you start the thread.

To safely stop the thread, I wait for <Ctrl>-C (keyboard interrupt) and tell the thread to stop itself.

In the initialization of the class, you also have a parameter pause to control how long to wait between tries.

Use the class ClipboardWatcher like in my example, replace the callback with what you do, e.g., lambda x: bitly(x, username, password).

Leave a Comment