Python работа с буфером обмена windows

How do I read text from the (windows) clipboard with python?

How do I read text from the (windows) clipboard with python?

dreftymac's user avatar

dreftymac

30.8k26 gold badges117 silver badges180 bronze badges

asked Sep 19, 2008 at 11:09

Foo42's user avatar

2

You can use the module called win32clipboard, which is part of pywin32.

Here is an example that first sets the clipboard data then gets it:

import win32clipboard

# set clipboard data
win32clipboard.OpenClipboard()
win32clipboard.EmptyClipboard()
win32clipboard.SetClipboardText('testing 123')
win32clipboard.CloseClipboard()

# get clipboard data
win32clipboard.OpenClipboard()
data = win32clipboard.GetClipboardData()
win32clipboard.CloseClipboard()
print data

An important reminder from the documentation:

When the window has finished examining or changing the clipboard,
close the clipboard by calling CloseClipboard. This enables other
windows to access the clipboard. Do not place an object on the
clipboard after calling CloseClipboard.

SuperStormer's user avatar

SuperStormer

4,8625 gold badges23 silver badges34 bronze badges

answered Sep 19, 2008 at 11:20

Sakin's user avatar

SakinSakin

3,2973 gold badges23 silver badges27 bronze badges

5

you can easily get this done through the built-in module Tkinter which is basically a GUI library. This code creates a blank widget to get the clipboard content from OS.

from tkinter import Tk  # Python 3
#from Tkinter import Tk # for Python 2.x
Tk().clipboard_get()

answered May 24, 2014 at 11:58

kmonsoor's user avatar

kmonsoorkmonsoor

7,2807 gold badges42 silver badges55 bronze badges

1

I found pyperclip to be the easiest way to get access to the clipboard from python:

  1. Install pyperclip:
    pip install pyperclip

  2. Usage:

import pyperclip
    
s = pyperclip.paste()
pyperclip.copy(s)
    
# the type of s is string

With supports Windows, Linux and Mac, and seems to work with non-ASCII characters, too.
Tested characters include ±°©©αβγθΔΨΦåäö

answered Jul 3, 2016 at 15:54

np8's user avatar

np8np8

25.2k10 gold badges86 silver badges93 bronze badges

6

If you don’t want to install extra packages, ctypes can get the job done as well.

import ctypes

CF_TEXT = 1

kernel32 = ctypes.windll.kernel32
kernel32.GlobalLock.argtypes = [ctypes.c_void_p]
kernel32.GlobalLock.restype = ctypes.c_void_p
kernel32.GlobalUnlock.argtypes = [ctypes.c_void_p]
user32 = ctypes.windll.user32
user32.GetClipboardData.restype = ctypes.c_void_p

def get_clipboard_text():
    user32.OpenClipboard(0)
    try:
        if user32.IsClipboardFormatAvailable(CF_TEXT):
            data = user32.GetClipboardData(CF_TEXT)
            data_locked = kernel32.GlobalLock(data)
            text = ctypes.c_char_p(data_locked)
            value = text.value
            kernel32.GlobalUnlock(data_locked)
            return value
    finally:
        user32.CloseClipboard()

print(get_clipboard_text())

answered Apr 25, 2014 at 5:54

kichik's user avatar

kichikkichik

32.1k6 gold badges92 silver badges110 bronze badges

5

The most upvoted answer above is weird in a way that it simply clears the Clipboard and then gets the content (which is then empty). One could clear the clipboard to be sure that some clipboard content type like «formated text» does not «cover» your plain text content you want to save in the clipboard.

The following piece of code replaces all newlines in the clipboard by spaces, then removes all double spaces and finally saves the content back to the clipboard:

import win32clipboard

win32clipboard.OpenClipboard()
c = win32clipboard.GetClipboardData()
win32clipboard.EmptyClipboard()
c = c.replace('n', ' ')
c = c.replace('r', ' ')
while c.find('  ') != -1:
    c = c.replace('  ', ' ')
win32clipboard.SetClipboardText(c)
win32clipboard.CloseClipboard()

answered Jun 19, 2012 at 8:00

born's user avatar

bornborn

5651 gold badge4 silver badges18 bronze badges

The python standard library does it…

try:
    # Python3
    import tkinter as tk
except ImportError:
    # Python2
    import Tkinter as tk

def getClipboardText():
    root = tk.Tk()
    # keep the window from showing
    root.withdraw()
    return root.clipboard_get()

ankostis's user avatar

ankostis

8,1123 gold badges45 silver badges61 bronze badges

answered Apr 4, 2018 at 8:42

Paul Sumpner's user avatar

2

For my console program the answers with tkinter above did not quite work for me because the .destroy() always gave an error,:

can’t invoke «event» command: application has been destroyed while executing…

or when using .withdraw() the console window did not get the focus back.

To solve this you also have to call .update() before the .destroy(). Example:

# Python 3
import tkinter

r = tkinter.Tk()
text = r.clipboard_get()
r.withdraw()
r.update()
r.destroy()

The r.withdraw() prevents the frame from showing for a milisecond, and then it will be destroyed giving the focus back to the console.

answered Jan 17, 2015 at 1:08

user136036's user avatar

user136036user136036

10.5k6 gold badges45 silver badges46 bronze badges

Use Pythons library Clipboard

Its simply used like this:

import clipboard
clipboard.copy("this text is now in the clipboard")
print clipboard.paste()  

answered Apr 27, 2016 at 10:19

Dan's user avatar

DanDan

1471 silver badge4 bronze badges

3

After whole 12 years, I have a solution and you can use it without installing any package.

from tkinter import Tk, TclError
from time import sleep

while True:
    try:
        clipboard = Tk().clipboard_get()
        print(clipboard)
        sleep(5)
    except TclError:
        print("Clipboard is empty.")
        sleep(5)

answered Apr 29, 2021 at 19:17

kirgizmustafa17's user avatar

A not very direct trick:

Use pyautogui hotkey:

Import pyautogui
pyautogui.hotkey('ctrl', 'v')

Therefore, you can paste the clipboard data as you like.

answered Jul 9, 2019 at 7:06

see2's user avatar

1

import pandas as pd
df = pd.read_clipboard()

answered Dec 7, 2021 at 4:21

Athii's user avatar

AthiiAthii

952 silver badges11 bronze badges

1

Why not try calling powershell?

import subprocess

def getClipboard():
    ret = subprocess.getoutput("powershell.exe -Command Get-Clipboard")
    return ret

answered Feb 18, 2022 at 5:36

东临碣石's user avatar

1

For users of Anaconda: distributions don’t come with pyperclip, but they do come with pandas which redistributes pyperclip:

>>> from pandas.io.clipboard import clipboard_get, clipboard_set
>>> clipboard_get()
'from pandas.io.clipboard import clipboard_get, clipboard_set'
>>> clipboard_set("Hello clipboard!")
>>> clipboard_get()
'Hello clipboard!'

I find this easier to use than pywin32 (which is also included in distributions).

answered Dec 6, 2021 at 16:14

asdf101's user avatar

asdf101asdf101

5295 silver badges18 bronze badges

I just need a python script that copies text to the clipboard.

After the script gets executed i need the output of the text to be pasted to another source.
Is it possible to write a python script that does this job?

M. A. Kishawy's user avatar

asked Jun 16, 2012 at 12:32

iamsiva11's user avatar

3

See Pyperclip. Example (taken from Pyperclip site):

import pyperclip
pyperclip.copy('The text to be copied to the clipboard.')
spam = pyperclip.paste()

Also, see Xerox. But it appears to have more dependencies.

vauhochzett's user avatar

vauhochzett

2,2442 gold badges17 silver badges36 bronze badges

answered Jun 16, 2012 at 12:35

robert's user avatar

robertrobert

32.4k8 gold badges52 silver badges72 bronze badges

4

On macOS, use subprocess.run to pipe your text to pbcopy:

import subprocess 
data = "hello world"
subprocess.run("pbcopy", text=True, input=data)

It will copy «hello world» to the clipboard.

Laszlo Treszkai's user avatar

answered Jun 28, 2013 at 18:27

kyle k's user avatar

kyle kkyle k

4,9048 gold badges30 silver badges45 bronze badges

5

To use native Python directories, use:

import subprocess

def copy2clip(txt):
    cmd='echo '+txt.strip()+'|clip'
    return subprocess.check_call(cmd, shell=True)

on Mac, instead:

import subprocess

def copy2clip(txt):
    cmd='echo '+txt.strip()+'|pbcopy'
    return subprocess.check_call(cmd, shell=True)

Then use:

copy2clip('This is on my clipboard!')

to call the function.

Community's user avatar

answered Dec 8, 2016 at 0:47

Binyamin's user avatar

BinyaminBinyamin

6098 silver badges17 bronze badges

8

PyQt5:

from PyQt5.QtWidgets import QApplication
import sys

def main():
    app = QApplication(sys.argv)
    cb = QApplication.clipboard()
    cb.clear(mode=cb.Clipboard )
    cb.setText("Copy to ClipBoard", mode=cb.Clipboard)
    # Text is now already in the clipboard, no need for further actions.
    sys.exit()

if __name__ == "__main__":
    main()

Community's user avatar

answered Nov 9, 2015 at 11:00

Akshay's user avatar

AkshayAkshay

4556 silver badges15 bronze badges

2

GTK3:

#!/usr/bin/python3

from gi.repository import Gtk, Gdk


class Hello(Gtk.Window):

    def __init__(self):
        super(Hello, self).__init__()
        clipboard = Gtk.Clipboard.get(Gdk.SELECTION_CLIPBOARD)
        clipboard.set_text("hello world", -1)
        Gtk.main_quit()


def main():
    Hello()
    Gtk.main()

if __name__ == "__main__":
    main()

answered Feb 25, 2015 at 15:29

Martin Thoma's user avatar

Martin ThomaMartin Thoma

118k153 gold badges590 silver badges913 bronze badges

1

I try this clipboard 0.0.4 and it works well.

https://pypi.python.org/pypi/clipboard/0.0.4

import clipboard
clipboard.copy("abc")  # now the clipboard content will be string "abc"
text = clipboard.paste()  # text will have the content of clipboard

answered Jun 28, 2016 at 6:34

Du Peng's user avatar

Du PengDu Peng

3432 silver badges3 bronze badges

2

One more answer to improve on:
https://stackoverflow.com/a/4203897/2804197
and https://stackoverflow.com/a/25476462/1338797 (Tkinter).

Tkinter is nice, because it’s either included with Python (Windows) or easy to install (Linux), and thus requires little dependencies for the end user.

Here I have a «full-blown» example, which copies the arguments or the standard input, to clipboard, and — when not on Windows — waits for the user to close the application:

import sys

try:
    from Tkinter import Tk
except ImportError:
    # welcome to Python3
    from tkinter import Tk
    raw_input = input

r = Tk()
r.withdraw()
r.clipboard_clear()

if len(sys.argv) < 2:
    data = sys.stdin.read()
else:
    data = ' '.join(sys.argv[1:])

r.clipboard_append(data)

if sys.platform != 'win32':
    if len(sys.argv) > 1:
        raw_input('Data was copied into clipboard. Paste and press ENTER to exit...')
    else:
        # stdin already read; use GUI to exit
        print('Data was copied into clipboard. Paste, then close popup to exit...')
        r.deiconify()
        r.mainloop()
else:
    r.destroy()

This showcases:

  • importing Tk across Py2 and Py3
  • raw_input and print() compatibility
  • «unhiding» Tk root window when needed
  • waiting for exit on Linux in two different ways.

Community's user avatar

answered Nov 4, 2015 at 13:35

Tomasz Gandor's user avatar

Tomasz GandorTomasz Gandor

7,9152 gold badges61 silver badges55 bronze badges

3

This is an altered version of @Martin Thoma’s answer for GTK3. I found that the original solution resulted in the process never ending and my terminal hung when I called the script. Changing the script to the following resolved the issue for me.

#!/usr/bin/python3

from gi.repository import Gtk, Gdk
import sys
from time import sleep

class Hello(Gtk.Window):

    def __init__(self):
        super(Hello, self).__init__()
        
        clipboardText = sys.argv[1]
        clipboard = Gtk.Clipboard.get(Gdk.SELECTION_CLIPBOARD)
        clipboard.set_text(clipboardText, -1)
        clipboard.store()


def main():
    Hello()
    
    

if __name__ == "__main__":
    main()

You will probably want to change what clipboardText gets assigned to, in this script it is assigned to the parameter that the script is called with.

On a fresh ubuntu 16.04 installation, I found that I had to install the python-gobject package for it to work without a module import error.

Neuron's user avatar

Neuron

4,8345 gold badges35 silver badges54 bronze badges

answered Apr 25, 2016 at 11:34

Programster's user avatar

ProgramsterProgramster

12k8 gold badges47 silver badges54 bronze badges

I just need a python script that copies text to the clipboard.

After the script gets executed i need the output of the text to be pasted to another source.
Is it possible to write a python script that does this job?

M. A. Kishawy's user avatar

asked Jun 16, 2012 at 12:32

iamsiva11's user avatar

3

See Pyperclip. Example (taken from Pyperclip site):

import pyperclip
pyperclip.copy('The text to be copied to the clipboard.')
spam = pyperclip.paste()

Also, see Xerox. But it appears to have more dependencies.

vauhochzett's user avatar

vauhochzett

2,2442 gold badges17 silver badges36 bronze badges

answered Jun 16, 2012 at 12:35

robert's user avatar

robertrobert

32.4k8 gold badges52 silver badges72 bronze badges

4

On macOS, use subprocess.run to pipe your text to pbcopy:

import subprocess 
data = "hello world"
subprocess.run("pbcopy", text=True, input=data)

It will copy «hello world» to the clipboard.

Laszlo Treszkai's user avatar

answered Jun 28, 2013 at 18:27

kyle k's user avatar

kyle kkyle k

4,9048 gold badges30 silver badges45 bronze badges

5

To use native Python directories, use:

import subprocess

def copy2clip(txt):
    cmd='echo '+txt.strip()+'|clip'
    return subprocess.check_call(cmd, shell=True)

on Mac, instead:

import subprocess

def copy2clip(txt):
    cmd='echo '+txt.strip()+'|pbcopy'
    return subprocess.check_call(cmd, shell=True)

Then use:

copy2clip('This is on my clipboard!')

to call the function.

Community's user avatar

answered Dec 8, 2016 at 0:47

Binyamin's user avatar

BinyaminBinyamin

6098 silver badges17 bronze badges

8

PyQt5:

from PyQt5.QtWidgets import QApplication
import sys

def main():
    app = QApplication(sys.argv)
    cb = QApplication.clipboard()
    cb.clear(mode=cb.Clipboard )
    cb.setText("Copy to ClipBoard", mode=cb.Clipboard)
    # Text is now already in the clipboard, no need for further actions.
    sys.exit()

if __name__ == "__main__":
    main()

Community's user avatar

answered Nov 9, 2015 at 11:00

Akshay's user avatar

AkshayAkshay

4556 silver badges15 bronze badges

2

GTK3:

#!/usr/bin/python3

from gi.repository import Gtk, Gdk


class Hello(Gtk.Window):

    def __init__(self):
        super(Hello, self).__init__()
        clipboard = Gtk.Clipboard.get(Gdk.SELECTION_CLIPBOARD)
        clipboard.set_text("hello world", -1)
        Gtk.main_quit()


def main():
    Hello()
    Gtk.main()

if __name__ == "__main__":
    main()

answered Feb 25, 2015 at 15:29

Martin Thoma's user avatar

Martin ThomaMartin Thoma

118k153 gold badges590 silver badges913 bronze badges

1

I try this clipboard 0.0.4 and it works well.

https://pypi.python.org/pypi/clipboard/0.0.4

import clipboard
clipboard.copy("abc")  # now the clipboard content will be string "abc"
text = clipboard.paste()  # text will have the content of clipboard

answered Jun 28, 2016 at 6:34

Du Peng's user avatar

Du PengDu Peng

3432 silver badges3 bronze badges

2

One more answer to improve on:
https://stackoverflow.com/a/4203897/2804197
and https://stackoverflow.com/a/25476462/1338797 (Tkinter).

Tkinter is nice, because it’s either included with Python (Windows) or easy to install (Linux), and thus requires little dependencies for the end user.

Here I have a «full-blown» example, which copies the arguments or the standard input, to clipboard, and — when not on Windows — waits for the user to close the application:

import sys

try:
    from Tkinter import Tk
except ImportError:
    # welcome to Python3
    from tkinter import Tk
    raw_input = input

r = Tk()
r.withdraw()
r.clipboard_clear()

if len(sys.argv) < 2:
    data = sys.stdin.read()
else:
    data = ' '.join(sys.argv[1:])

r.clipboard_append(data)

if sys.platform != 'win32':
    if len(sys.argv) > 1:
        raw_input('Data was copied into clipboard. Paste and press ENTER to exit...')
    else:
        # stdin already read; use GUI to exit
        print('Data was copied into clipboard. Paste, then close popup to exit...')
        r.deiconify()
        r.mainloop()
else:
    r.destroy()

This showcases:

  • importing Tk across Py2 and Py3
  • raw_input and print() compatibility
  • «unhiding» Tk root window when needed
  • waiting for exit on Linux in two different ways.

Community's user avatar

answered Nov 4, 2015 at 13:35

Tomasz Gandor's user avatar

Tomasz GandorTomasz Gandor

7,9152 gold badges61 silver badges55 bronze badges

3

This is an altered version of @Martin Thoma’s answer for GTK3. I found that the original solution resulted in the process never ending and my terminal hung when I called the script. Changing the script to the following resolved the issue for me.

#!/usr/bin/python3

from gi.repository import Gtk, Gdk
import sys
from time import sleep

class Hello(Gtk.Window):

    def __init__(self):
        super(Hello, self).__init__()
        
        clipboardText = sys.argv[1]
        clipboard = Gtk.Clipboard.get(Gdk.SELECTION_CLIPBOARD)
        clipboard.set_text(clipboardText, -1)
        clipboard.store()


def main():
    Hello()
    
    

if __name__ == "__main__":
    main()

You will probably want to change what clipboardText gets assigned to, in this script it is assigned to the parameter that the script is called with.

On a fresh ubuntu 16.04 installation, I found that I had to install the python-gobject package for it to work without a module import error.

Neuron's user avatar

Neuron

4,8345 gold badges35 silver badges54 bronze badges

answered Apr 25, 2016 at 11:34

Programster's user avatar

ProgramsterProgramster

12k8 gold badges47 silver badges54 bronze badges

7 / 6 / 7

Регистрация: 10.08.2015

Сообщений: 63

1

27.08.2015, 11:01. Показов 62923. Ответов 10


Возникла необходимость написать программу работающую с буфером обмена Windows. Поиск в гугле по схожим запросам практически не дал результатов. Только о Clipboard в Tkinter, но без подробных описаний или примеров.
Какие есть методы/функции для работы с буфером обмена в Python? Где найти информацию о нём?

P.S. Желательны ресурсы на русском языке.

__________________
Помощь в написании контрольных, курсовых и дипломных работ, диссертаций здесь



0



ВАСИЛЕВС

561 / 484 / 168

Регистрация: 14.02.2012

Сообщений: 1,561

27.08.2015, 11:18

2

Я нашел модуль pyperclip
Пример работы

Python
1
2
3
4
>>> import pyperclip
>>> pyperclip.copy('The text to be copied to the clipboard.')
>>> pyperclip.paste()
'The text to be copied to the clipboard.'



2



7 / 6 / 7

Регистрация: 10.08.2015

Сообщений: 63

27.08.2015, 11:45

 [ТС]

3

Подобное я тоже находил. Но paste/copy маловато для моей программы.
Необходимо что бы при нажатии клавиш(любых ctrl+c к примеру) питон копировал к себе в переменную, выполнял с содержимым действия и возвращал в буфер изменённое значение.

К примеру я выделяю в браузере «100» нажимаю ctrL+c. Значение 100 записывается в переменную x. Происходит действие x+50. И при нажатии ctrl+v возвращал «150»



0



Эксперт Python

4606 / 2027 / 359

Регистрация: 17.03.2012

Сообщений: 10,081

Записей в блоге: 6

27.08.2015, 11:46

4

В PyQT есть QClipboard.



0



akzo

71 / 67 / 6

Регистрация: 08.08.2013

Сообщений: 286

Записей в блоге: 8

27.08.2015, 11:59

5

Лучший ответ Сообщение было отмечено Protos73 как решение

Решение

Python
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
# -*- coding:utf-8 -*-
from Tkinter import *
 
 
#окно
tk=Tk()
tk.geometry("300x200+100+100")
 
#функция читающая буфер
def read(e):
    
    bufer_data['text'] = tk.clipboard_get()
 
#функция записывающая в буфер   
def write(e):
    tk.clipboard_clear()
    tk.clipboard_append('akzo rulez:)')
 
#текст с содержанием буфера
bufer_data = Label(tk,text="No Data")
bufer_data.pack(expand='YES')
 
#кнопка вызывающая фкнуцию для чтения
button = Button(tk, text="Read Bufer Data")
button.pack(expand='YES')
button.bind("<Button-1>",read)
 
#кнопка для записи
button = Button(tk, text="Write Bufer Data")
button.pack(expand='YES')
button.bind("<Button-1>",write)
 
 
tk.mainloop()

Это простая программа в процедурном стиле, к этому добавляете еще знания отсюда: http://ehow.kurortmag.net/page… aad37.html
Немножко додумываете и радуетесь жизни



1



1483 / 457 / 52

Регистрация: 10.04.2009

Сообщений: 7,874

23.02.2021, 13:36

6

здравствуйте гугл по запросу
питон из буфера обмена поместить в переменную
привёл меня сюда-есть пример попроще? без Tkinter-типа инпута? спс



0



Garry Galler

Эксперт Python

5403 / 3827 / 1214

Регистрация: 28.10.2013

Сообщений: 9,554

Записей в блоге: 1

23.02.2021, 14:25

7

Цитата
Сообщение от Ципихович Эндрю
Посмотреть сообщение

есть пример попроще?

Ты как всегда решил сначала спросить и только потом попробовать?

Python
1
2
3
4
5
6
>>> import pyperclip
>>> # сейчас это в буфере обмена так как я туда скопировал
>>> x = pyperclip.paste()
>>> print(x)
# сейчас это в буфере обмена так как я туда скопировал
>>>



1



Ципихович Эндрю

1483 / 457 / 52

Регистрация: 10.04.2009

Сообщений: 7,874

23.02.2021, 14:41

8

нет нужно по аналогии

Python
1
n = int(input('Введите количество строк, и нажмите Enter'))
Python
1
print('Скопируйте нужный текст, и нажмите Enter')

и после того как скопировали и нажали ОК в переменную
inpt = попадает скопированное



0



Garry Galler

Эксперт Python

5403 / 3827 / 1214

Регистрация: 28.10.2013

Сообщений: 9,554

Записей в блоге: 1

23.02.2021, 16:59

9

Цитата
Сообщение от Ципихович Эндрю
Посмотреть сообщение

нет нужно по аналогии

Не понимаю твоей аналогии.
pyperclip это инструмент для работы с буфером обмена. Все прочие работают аналогично.
Если тебе нужно что-то иное — пиши сам.

Добавлено через 51 минуту
Или ты сам не понял своей же аналогии.
У буфера обмена есть ровно две функции: copy (скопировать что-то), paste (вставить из буфера в другое место):

Python
1
2
3
4
5
>>> pyperclip.copy("# сейчас это в буфере обмена так как я туда скопировал")
>>> x= pyperclip.paste()
>>> print(x)
# сейчас это в буфере обмена так как я туда скопировал
>>>

А всякого рода нажатия OK или Enter никакого отношения к работе буфера не имеют.
Он работает только с Ctrl-C и Ctrl-V.



2



1483 / 457 / 52

Регистрация: 10.04.2009

Сообщений: 7,874

23.02.2021, 17:10

10

Цитата
Сообщение от Garry Galler
Посмотреть сообщение

А всякого рода нажатия OK или Enter никакого отношения к работе буфера не имеют.
Он работает только с Ctrl-C и Ctrl-V.

я это уже вспомнил, есть инструменты для уточнения последнегопредпоследнего и других по счёту элементов — что в буфере находятся?

Добавлено через 1 минуту

Цитата
Сообщение от Garry Galler
Посмотреть сообщение

ровно две функции: copy (скопировать что-то), paste (вставить из буфера в другое место)

ну так и скопировать что-то и залетать в значение переменной



0



Эксперт Python

5403 / 3827 / 1214

Регистрация: 28.10.2013

Сообщений: 9,554

Записей в блоге: 1

23.02.2021, 17:22

11

Цитата
Сообщение от Ципихович Эндрю
Посмотреть сообщение

что в буфере находятся

В буфере находится ровно один элемент (не считая того, что он может быть одновременно в нескольких форматах). Нет никаких первых-последних.
Что туда положилскопировал, то там сейчас и лежит. Каждое новое копирование замещает предыдущее.
У системного буфера нет никакой истории. Историю копирований сохраняют только специальные программы имитирующие такой буфер — clipdiary, например.
Или буфер MS Office и т.д.



1



Язык программирования Python

Pyperclip – это небольшой кроссплатформенный (Windows, Linux, OS X) модуль для копирования и вставки текста в буфер обмена, разработанный Элом Свейгартом. Он работает на Python 2 и 3 и устанавливается с помощью pip:

pip install pyperclip

Содержание

  • 1 Функционал
  • 2 Пример

Функционал

В системах Microsoft Windows дополнительный пакет не требуется, поскольку он взаимодействует непосредственно с Windows API через модуль ctypes.

В дистрибутивах Linux модуль использует одну из следующих программ: xclip и xsel. Если какие-либо из них не установлены по умолчанию, их можно получить, выполнив команду:

sudo apt-get install xclip sudo apt-get install xsel

Code language: JavaScript (javascript)

Если таковых нет, pyperclip может использовать функции Qt (PyQt 4) или GTK (недоступно в Python 3), если они установлены.

В Mac OS X для этого используются pbcopy и pbpaste.

Пример

>>> import pyperclip as clipboard # Копирование текста в буфер обмена. >>> clipboard.copy("Текст для копирования") # Получить доступ к содержимому (вставить). >>> clipboard.paste() 'Текст для копирования'

Code language: PHP (php)

Модуль clipboard.Работа с буфером обмена
Знатокам в питоне будет неинтересно. Возможно будет интересно глянуть начинающим программистам.Бывало раньше интересовал подобный вопрос. Вот решил накатать такую статейку. Пусть будет до кучи Автор статьи я(zaterehniy). Работа довольно таки простая, всего две команды одна команда записывает информацию в буфер, другая записанную информацию достает из него. Конечно же чтобы наше приложение на питоне могло работать с буфером нужно импортировать сам модуль.

import clipboard

Для записи данных в буфер служит следуюший метод —
clipboard.Set() (здесь стоит обратить внимание что Set писать следует именно с большой буквы! Если напишем с маленькой- set, то консоль выдаст ошибку),в скобках пишем любой текст,который мы поместим в буфер,не забываем про ковычки которые указывают питону что внутри них просто текст.

clipboard.Set(‘luboi tekst’)

Для того чтобы достать данные из буфера пишем следующую команду(достать просто командой get не получится).

clipboard.Get()

a = clipboard.Get()
print ‘ module clipboard= ‘a
module clipboard = luboi tekst


Источник новости:

I was looking for ways to listen to the clipboard and get called for updates as its content changes.
I found a couple of ways to achieve this in Python. Some solutions poll for changes, others use ctypes and Win32 APIs.

Working with C bindings in Python is frustrating. The debugger doesn’t work well with pointers and C types. You have to build your own C structs to unpack a pointer. Win32 APIs are no exception, as they’re written in C/C++ and Python is probably not the best language to use them. But still, it works well enough for our purposes.

We’ll explore how do to it in Python using Win32 APIs, or alternatively integrating a utility I’ve written in C# that retrieves clipboard contents or streams updates to it. I had written this earlier when I didn’t know much about Win32 APIs or how to use them, but it still functions well, so I’m leaving it here in this post as reference.

To make working with Win32 APIs easier, we need to install pywin32 package which provides most of the primitives and types for Win32 APIs, though it’s not a strict dependency.

Monitoring clipboard updates

Windows provides a couple of methods for data exchange between applications. Clipboard is one of them. All applications have access to it. But we first need to create a primitive «application» that Windows recognizes. We subscribe it for the clipboard updates.

Windows uses windows (hah!) as the building block of applications. I’ve written about how windows and messaging works on Windows in another post where I explored USB hotplugging events, which might be worth reading.

Let’s create a window, and set print function as its window procedure:

import win32api, win32gui

def create_window() -> int:
    """
    Create a window for listening to messages
    :return: window hwnd
    """
    wc = win32gui.WNDCLASS()
    wc.lpfnWndProc = print
    wc.lpszClassName = 'demo'
    wc.hInstance = win32api.GetModuleHandle(None)
    class_atom = win32gui.RegisterClass(wc)
    return win32gui.CreateWindow(class_atom, 'demo', 0, 0, 0, 0, 0, 0, 0, wc.hInstance, None)

if __name__ == '__main__':
    hwnd = create_window()
    win32gui.PumpMessages()

When we run it doesn’t do much except to dump messages sent by Windows to console. We receive the first message WM_DWMNCRENDERINGCHANGED, which doesn’t concern us.

We need to register this window as a «clipboard format listener» using AddClipboardFormatListener API, to get notified by Windows whenever the contents of the clipboard change.

import ctypes
# ...

if __name__ == '__main__':
    hwnd = create_window()
    ctypes.windll.user32.AddClipboardFormatListener(hwnd)
    win32gui.PumpMessages()

Now when we run this, it still prints the previous message, but when you copy something to the clipboard it receives another message:

2033456 799 1 0
2033456 797 8 0

Decoding the second message:

Value Hex Message
797 0x031D WM_CLIPBOARDUPDATE 🥳

We’ve received a WM_CLIPBOARDUPDATE message notifying us that the clipboard content has changed. Now we can build our script around it.

import threading
import ctypes
import win32api, win32gui

class Clipboard:
    def _create_window(self) -> int:
        """
        Create a window for listening to messages
        :return: window hwnd
        """
        wc = win32gui.WNDCLASS()
        wc.lpfnWndProc = self._process_message
        wc.lpszClassName = self.__class__.__name__
        wc.hInstance = win32api.GetModuleHandle(None)
        class_atom = win32gui.RegisterClass(wc)
        return win32gui.CreateWindow(class_atom, self.__class__.__name__, 0, 0, 0, 0, 0, 0, 0, wc.hInstance, None)

    def _process_message(self, hwnd: int, msg: int, wparam: int, lparam: int):
        WM_CLIPBOARDUPDATE = 0x031D
        if msg == WM_CLIPBOARDUPDATE:
            print('clipboard updated!')
        return 0

    def listen(self):
        def runner():
            hwnd = self._create_window()
            ctypes.windll.user32.AddClipboardFormatListener(hwnd)
            win32gui.PumpMessages()

        th = threading.Thread(target=runner, daemon=True)
        th.start()
        while th.is_alive():
            th.join(0.25)

if __name__ == '__main__':
    clipboard = Clipboard()
    clipboard.listen()

One thing we need to watch out for is that because win32gui.PumpMessages() is blocking, we cannot stop the script using Ctrl + C. So we run it inside a thread, which lets KeyboardInterrupt to bubble up and terminate the script.

When we run it, and copy something (text, files) and check the console, we can see it prints clipboard updated!.

Now that we have the notification working, let’s retrieve the what’s actually in the clipboard.

Getting clipboard contents

Windows clipboard has a concept called «clipboard format». When you copy something, (depending on application) the payload is also attached a bunch of metadata, allowing it to be used in various contexts. For example, when you copy a table from a webpage, you have the option to paste it as plain text, or paste it in Excel and have it formatted as a table. You can copy files, images, screenshots into the clipboard and each payload gets stored formatted (again, depending on how the application sets the clipboard content).

Therefore, if we want to get the clipboard contents, we need to specify which format we want in. For now, we’ll be dealing with:

Format Value Description
CF_UNICODETEXT 13 Unicode text format
CF_TEXT 1 Text format for ANSI text
CF_HDROP 15 List of files
CF_BITMAP 2 Images e.g. screenshots

To read the clipboard, we’ll use OpenClipboard to set a lock first. This ensures other programs can’t modify the clipboard while we’re trying to read it. We need to release the lock with CloseClipboard once we’re done.

Then we’ll call IsClipboardFormatAvailable to query a format, then get its contents using GetClipboardData, or fallback to other formats.

from pathlib import Path
from dataclasses import dataclass
from typing import Union, List, Optional

import win32clipboard, win32con

@dataclass
class Clip:
    type: str
    value: Union[str, List[Path]]
    
def read_clipboard() -> Optional[Clip]:
    try:
        win32clipboard.OpenClipboard()
        if win32clipboard.IsClipboardFormatAvailable(win32con.CF_HDROP):
            data: tuple = win32clipboard.GetClipboardData(win32con.CF_HDROP)
            return Clip('files', [Path(f) for f in data])
        elif win32clipboard.IsClipboardFormatAvailable(win32con.CF_UNICODETEXT):
            data: str = win32clipboard.GetClipboardData(win32con.CF_UNICODETEXT)
            return Clip('text', data)
        elif win32clipboard.IsClipboardFormatAvailable(win32con.CF_TEXT):
            data: bytes = win32clipboard.GetClipboardData(win32con.CF_TEXT)
            return Clip('text', data.decode())
        elif win32clipboard.IsClipboardFormatAvailable(win32con.CF_BITMAP):
            # TODO: handle screenshots
            pass
        return None
    finally:
        win32clipboard.CloseClipboard()

if __name__ == '__main__':
    print(read_clipboard())

When we run it, and try copying some text or files, it prints the contents to the console:

Clip(type='text', value='read_clipboard')
Clip(type='files', value=[WindowsPath('C:/Python39/vcruntime140_1.dll'), WindowsPath('C:/Python39/python.exe')])

Now let’s bring it all together:

Clipboard listener in Python

I’ve placed read_clipboard inside Clipboard class, which creates a window and subscribes to clipboard updates. When the clipboard content changes, it triggers suitable callbacks with the parsed content.

For convenience, you can enable trigger_at_start to trigger callbacks with the current clipboard content immediately after listening.

import ctypes
import threading
from dataclasses import dataclass
from pathlib import Path
from typing import Callable, Union, List, Optional

import win32api, win32clipboard, win32con, win32gui

class Clipboard:
    @dataclass
    class Clip:
        type: str
        value: Union[str, List[Path]]

    def __init__(
            self,
            trigger_at_start: bool = False,
            on_text: Callable[[str], None] = None,
            on_update: Callable[[Clip], None] = None,
            on_files: Callable[[str], None] = None,
    ):
        self._trigger_at_start = trigger_at_start
        self._on_update = on_update
        self._on_files = on_files
        self._on_text = on_text

    def _create_window(self) -> int:
        """
        Create a window for listening to messages
        :return: window hwnd
        """
        wc = win32gui.WNDCLASS()
        wc.lpfnWndProc = self._process_message
        wc.lpszClassName = self.__class__.__name__
        wc.hInstance = win32api.GetModuleHandle(None)
        class_atom = win32gui.RegisterClass(wc)
        return win32gui.CreateWindow(class_atom, self.__class__.__name__, 0, 0, 0, 0, 0, 0, 0, wc.hInstance, None)

    def _process_message(self, hwnd: int, msg: int, wparam: int, lparam: int):
        WM_CLIPBOARDUPDATE = 0x031D
        if msg == WM_CLIPBOARDUPDATE:
            self._process_clip()
        return 0

    def _process_clip(self):
        clip = self.read_clipboard()
        if not clip:
            return

        if self._on_update:
            self._on_update(clip)
        if clip.type == 'text' and self._on_text:
            self._on_text(clip.value)
        elif clip.type == 'files' and self._on_text:
            self._on_files(clip.value)
    
    @staticmethod
    def read_clipboard() -> Optional[Clip]:
        try:
            win32clipboard.OpenClipboard()

            def get_formatted(fmt):
                if win32clipboard.IsClipboardFormatAvailable(fmt):
                    return win32clipboard.GetClipboardData(fmt)
                return None

            if files := get_formatted(win32con.CF_HDROP):
                return Clipboard.Clip('files', [Path(f) for f in files])
            elif text := get_formatted(win32con.CF_UNICODETEXT):
                return Clipboard.Clip('text', text)
            elif text_bytes := get_formatted(win32con.CF_TEXT):
                return Clipboard.Clip('text', text_bytes.decode())
            elif bitmap_handle := get_formatted(win32con.CF_BITMAP):
                # TODO: handle screenshots
                pass

            return None
        finally:
            win32clipboard.CloseClipboard()

    def listen(self):
        if self._trigger_at_start:
            self._process_clip()

        def runner():
            hwnd = self._create_window()
            ctypes.windll.user32.AddClipboardFormatListener(hwnd)
            win32gui.PumpMessages()

        th = threading.Thread(target=runner, daemon=True)
        th.start()
        while th.is_alive():
            th.join(0.25)


if __name__ == '__main__':
    clipboard = Clipboard(on_update=print, trigger_at_start=True)
    clipboard.listen()

When we run it and copy some text, or some files, it dumps the clipboard content just as we want it.

Clipboard.Clip(type='text', value='Clipboard')
Clipboard.Clip(type='files', value=[WindowsPath('C:/Python39/python.exe')])

I haven’t managed to retrieve bitmap from the clipboard when taking a screenshot yet, though it shouldn’t be too difficult.

It should prove useful for the use case where when you take a screenshot, you can save it automatically as PNG, upload it and copy its URL to clipboard, ready for pasting.

Using dumpclip: polling for changes

Before I could navigate around Win32 APIs easily, I used higher level APIs provided in C# to listen to the clipboard. On that end, I created a mini utility called dumpclip that prints the clipboard content to console as JSON or streams clipboard updates.

The first version of dumpclip had a single function: dumping the clipboard content to console as JSON.

> dumpclip.v1.exe
{"text":"monitor"}

Calling it from Python is quite straightforward using subprocess module. But that also meant polling for changes every second.

import json
import subprocess
import threading
from time import sleep
from typing import Callable


def get_clipboard() -> dict:
    proc = subprocess.run(
        ["dumpclip.v1.exe"],
        stdout=subprocess.PIPE,
        text=True,
    )
    if proc.returncode != 0:
        return {}
    return json.loads(proc.stdout)


def monitor_clipboard(on_change: Callable[[dict], None]) -> None:
    def monitor():
        old = None
        while True:
            new = get_clipboard()
            if old != new:
                on_change(new)
                old = new
            sleep(1)

    th = threading.Thread(target=monitor)
    th.start()

    th.join()


if __name__ == "__main__":
    monitor_clipboard(on_change=print)

It’s functional, but we can do better.

Using dumpclip: streaming clipboard updates

The second iteration of dumpclip involved using Win32 APIs. I’ve used AddClipboardFormatListener to register a callback for clipboard changes in C#, then retrieved & dumped its content as the new content came in.

> dumpclip.v2.exe --listen
{"text":"ClipboardChanged"}
{"text":"monitor"}
{"files":["D:\path\to\file.ext"]}
...

This worked much better. I can process its stdout stream, and trigger a callback directly, instead of polling for changes. But dumpclip launched in listener mode never terminates. We need to read its stdout in real-time.

To stream stdout of a process, we need to launch it with subprocess.Popen and pipe its output to subprocess.PIPE.
Then we can read its stdout in a separate thread. Because, the main thread that launches the process will be waiting for the process to terminate (although it never will).

import json
import subprocess
import threading
from typing import Callable

def monitor_clipboard(on_change: Callable[[dict], None]) -> None:
    def read_stdout(proc: subprocess.Popen):
        for line in iter(proc.stdout.readline, ""):
            if line.strip():
                payload = json.loads(line)
                on_change(payload)

    proc = subprocess.Popen(
        ["dumpclip.v2.exe", "--listen"],
        text=True,
        stdout=subprocess.PIPE,
    )
    th = threading.Thread(
        target=read_stdout,
        args=(proc,),
    )
    th.start()
    try:
        proc.wait()
    except KeyboardInterrupt:
        proc.kill()
        raise

if __name__ == "__main__":
    monitor_clipboard(on_change=print)

Because the process doesn’t terminate, the thread that consumes its output doesn’t stop, either.
It keeps processing the output as new content comes in, and idles if there’s nothing to consume, as proc.stdout.readline() call is blocking.
When the process gets killed, proc.stdout stops blocking and the thread terminates.

To prevent blocking interrupt signal and to allow the script and the process terminate, we need to .wait() the subprocess. This allows KeyboardInterrupt to bubble up and terminate the script (and its subprocesses) when we hit Ctrl + C.

Using dumpclip: async workflow

Just for kicks, I wanted to implement the same operation in async. It turned out to be more straightforward to write and consume. One caveat is that you have to create a wrapper async function to use async/await keywords, so I had to add a main function to do that.

import asyncio
import json
from pathlib import Path
from typing import AsyncIterable

async def monitor_clipboard() -> AsyncIterable[dict]:
    proc = await asyncio.subprocess.create_subprocess_exec(
        "dumpclip.exe",
        "--listen",
        cwd=str(Path(__file__).parent.resolve()),
        stdout=asyncio.subprocess.PIPE,
    )

    while True:
        if raw_bytes := await proc.stdout.readline():
            text = raw_bytes.decode().strip()
            if text:
                yield json.loads(text)

if __name__ == "__main__":
    async def main():
        async for clip in monitor_clipboard():
            print(clip)

    asyncio.get_event_loop().run_until_complete(main())

That’s it.
Cheers ✌

If you’ve found this post useful, consider sharing it.



Как читать текст из буфера обмена (windows) из python?


1625  


10  

10 ответов:

вы можете использовать модуль под названием win32clipboard, которая является частью pywin32.

вот пример, который сначала устанавливает данные буфера обмена, а затем получает его:

import win32clipboard

# set clipboard data
win32clipboard.OpenClipboard()
win32clipboard.EmptyClipboard()
win32clipboard.SetClipboardText('testing 123')
win32clipboard.CloseClipboard()

# get clipboard data
win32clipboard.OpenClipboard()
data = win32clipboard.GetClipboardData()
win32clipboard.CloseClipboard()
print data

важное напоминание из документации:

когда окно закончит изучение или изменение буфера обмена,
закройте буфер обмена, вызвав CloseClipboard. Это позволяет другим
окна доступа к буферу обмена. Не устанавливайте объект на этот
буфер обмена после вызова CloseClipboard.

вы можете легко сделать это через встроенный модуль Tkinter который в основном является библиотекой GUI. Этот код создает пустой виджет для получения содержимого буфера обмена из ОС.

#from tkinter import Tk  # Python 3
from Tkinter import Tk
Tk().clipboard_get()

самый популярный ответ выше странный в том смысле, что он просто очищает буфер обмена, а затем получает содержимое (которое затем пусто). Можно очистить буфер обмена, чтобы убедиться, что какой-то тип содержимого буфера обмена, например «форматированный текст», не «покрывает» ваш обычный текстовый контент, который вы хотите сохранить в буфере обмена.

следующий фрагмент кода заменяет все символы новой строки в буфер обмена пробел, а затем удаляет все двойные пробелы и, наконец, сохраняет содержимое обратно буфер обмена:

import win32clipboard

win32clipboard.OpenClipboard()
c = win32clipboard.GetClipboardData()
win32clipboard.EmptyClipboard()
c = c.replace('n', ' ')
c = c.replace('r', ' ')
while c.find('  ') != -1:
    c = c.replace('  ', ' ')
win32clipboard.SetClipboardText(c)
win32clipboard.CloseClipboard()

Если вы не хотите устанавливать дополнительные пакеты, ctypes может сделать эту работу также.

import ctypes

CF_TEXT = 1

kernel32 = ctypes.windll.kernel32
user32 = ctypes.windll.user32

user32.OpenClipboard(0)
if user32.IsClipboardFormatAvailable(CF_TEXT):
    data = user32.GetClipboardData(CF_TEXT)
    data_locked = kernel32.GlobalLock(data)
    text = ctypes.c_char_p(data_locked)
    print(text.value)
    kernel32.GlobalUnlock(data_locked)
else:
    print('no text in clipboard')
user32.CloseClipboard()

для меня консольная программа ответы с tkinter выше, не совсем Работа для меня, потому что .destroy() всегда давал ошибку,:

не удается вызвать команду «событие»: приложение было уничтожено во время выполнения…

или при использовании .withdraw () окно консоли не вернуло фокус обратно.

чтобы решить эту проблему, вы также должны позвонить .обновление () перед началом .уничтожать.)( Пример:

# Python 3
import tkinter

r = tkinter.Tk()
text = r.clipboard_get()
r.withdraw()
r.update()
r.destroy()

Р.снять() предотвращает отображение кадра в течение миллисекунды, а затем он будет уничтожен, возвращая фокус на консоль.

использовать библиотеку питонов буфер обмена

его просто использовали так:

import clipboard
clipboard.copy("this text is now in the clipboard")
print clipboard.paste()  

я узнал, что это был самый простой способ получить доступ к буферу обмена из Python:

1) Установите pyperclip:
pip install pyperclip

2) Использование:

import pyperclip

s = pyperclip.paste()
pyperclip.copy(s)

# the type of s is string

протестировано на 64-битном Win10, Python 3.5. Кажется, работает и с не-ASCII символами.
Проверенные символы включают ±°©©αβγδδψφåäö

стандартная библиотека Python делает это…

try:
    # Python2
    import Tkinter as tk
except ImportError:
    # Python3
    import tkinter as tk

def getClipboardText():
    root = tk.Tk()
    # keep the window from showing
    root.withdraw()
    return root.clipboard_get()

Понравилась статья? Поделить с друзьями:
  • Python программа для windows скачать бесплатно
  • Python приложение для windows в трее
  • Python переместить файл в другую папку windows
  • Python переключиться на другое окно windows
  • Python открыть папку в проводнике windows