Как скопировать строку в буфер обмена в Windows с помощью Python?


Я пытаюсь сделать базовое приложение Windows, которое строит строку из пользовательского ввода, а затем добавляет ее в буфер обмена. Как скопировать строку в буфер обмена с помощью Python?

16 151

16 ответов:

на самом деле pywin32 и ctypes кажется перебор для этой простой задачи. Tkinter это кросс-платформенный графический интерфейс, который поставляется с Python по умолчанию и имеет методы доступа к буферу обмена наряду с другими классными вещами.

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

from Tkinter import Tk
r = Tk()
r.withdraw()
r.clipboard_clear()
r.clipboard_append('i can has clipboardz?')
r.update() # now it stays on the clipboard after the window is closed
r.destroy()

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

если вы используете Python 3, заменить TKinter с tkinter.

у меня не было решения, просто обходной путь.

Windows Vista и далее имеет встроенную команду под названием clip что берет вывод команды из командной строки и помещает его в буфер обмена. Например, ipconfig | clip.

поэтому я сделал функцию с os модуль, который принимает строку и добавляет ее в буфер обмена с помощью встроенного решения для Windows.

import os
def addToClipBoard(text):
    command = 'echo ' + text.strip() + '| clip'
    os.system(command)

# Example
addToClipBoard('penny lane')

# Penny Lane is now in your ears, eyes, and clipboard.

как уже отмечалось в комментариях, однако, одним из недостатков этого подхода является что за echo команда автоматически добавляет новую строку в конец текста. Чтобы избежать этого, вы можете использовать измененную версию команды:

def addToClipBoard(text):
    command = 'echo | set /p nul=' + text.strip() + '| clip'
    os.system(command)

если вы используете Windows XP, он будет работать только после выполнения шагов в копировать и вставлять из командной строки Windows XP Pro прямо в буфер обмена.

вы также можете использовать ctypes, чтобы подключиться к API Windows и избежать массивного пакета pywin32. Это то, что я использую (извините за плохой стиль, но идея есть):

import ctypes

# Get required functions, strcpy..
strcpy = ctypes.cdll.msvcrt.strcpy
ocb = ctypes.windll.user32.OpenClipboard    # Basic clipboard functions
ecb = ctypes.windll.user32.EmptyClipboard
gcd = ctypes.windll.user32.GetClipboardData
scd = ctypes.windll.user32.SetClipboardData
ccb = ctypes.windll.user32.CloseClipboard
ga = ctypes.windll.kernel32.GlobalAlloc    # Global memory allocation
gl = ctypes.windll.kernel32.GlobalLock     # Global memory Locking
gul = ctypes.windll.kernel32.GlobalUnlock
GMEM_DDESHARE = 0x2000

def Get():
  ocb(None) # Open Clip, Default task

  pcontents = gcd(1) # 1 means CF_TEXT.. too lazy to get the token thingy...

  data = ctypes.c_char_p(pcontents).value

  #gul(pcontents) ?
  ccb()

  return data

def Paste(data):
  ocb(None) # Open Clip, Default task

  ecb()

  hCd = ga(GMEM_DDESHARE, len(bytes(data,"ascii")) + 1)

  pchData = gl(hCd)

  strcpy(ctypes.c_char_p(pchData), bytes(data, "ascii"))

  gul(hCd)

  scd(1, hCd)

  ccb()

можно использовать pyperclip - кросс-платформенный модуль буфера обмена. Или Xerox - аналогичный модуль, за исключением того, что требуется модуль win32 Python для работы в Windows.

вы можете использовать отличные панды, которые имеют встроенную поддержку буфера обмена, но вам нужно пройти через фрейм данных.

import pandas as pd
df=pd.DataFrame(['Text to copy'])
df.to_clipboard(index=False,header=False)

похоже, вам нужно добавить win32clipboard на ваш сайт-пакеты. Это часть пакета pywin32

по какой-то причине я никогда не мог заставить решение Tk работать на меня. решение капаче гораздо более работоспособен, но форматирование противоречит моему стилю и не работает с Unicode. Вот модифицированная версия.

import ctypes

OpenClipboard = ctypes.windll.user32.OpenClipboard
EmptyClipboard = ctypes.windll.user32.EmptyClipboard
GetClipboardData = ctypes.windll.user32.GetClipboardData
SetClipboardData = ctypes.windll.user32.SetClipboardData
CloseClipboard = ctypes.windll.user32.CloseClipboard
CF_UNICODETEXT = 13

GlobalAlloc = ctypes.windll.kernel32.GlobalAlloc
GlobalLock = ctypes.windll.kernel32.GlobalLock
GlobalUnlock = ctypes.windll.kernel32.GlobalUnlock
GlobalSize = ctypes.windll.kernel32.GlobalSize
GMEM_MOVEABLE = 0x0002
GMEM_ZEROINIT = 0x0040

unicode_type = type(u'')

def get():
    text = None
    OpenClipboard(None)
    handle = GetClipboardData(CF_UNICODETEXT)
    pcontents = GlobalLock(handle)
    size = GlobalSize(handle)
    if pcontents and size:
        raw_data = ctypes.create_string_buffer(size)
        ctypes.memmove(raw_data, pcontents, size)
        text = raw_data.raw.decode('utf-16le').rstrip(u'')
    GlobalUnlock(handle)
    CloseClipboard()
    return text

def put(s):
    if not isinstance(s, unicode_type):
        s = s.decode('mbcs')
    data = s.encode('utf-16le')
    OpenClipboard(None)
    EmptyClipboard()
    handle = GlobalAlloc(GMEM_MOVEABLE | GMEM_ZEROINIT, len(data) + 2)
    pcontents = GlobalLock(handle)
    ctypes.memmove(pcontents, data, len(data))
    GlobalUnlock(handle)
    SetClipboardData(CF_UNICODETEXT, handle)
    CloseClipboard()

paste = get
copy = put

вышеизложенное изменилось с момента создания этого ответа, чтобы лучше справляться с расширенными символами Юникода и Python 3. Он был протестирован как в Python 2.7 и 3.5, и работает даже с emoji, такими как \U0001f601 ().

Я пробовал различные решения, но это самый простой, который проходит мой тест:

#coding=utf-8

import win32clipboard  # http://sourceforge.net/projects/pywin32/

def copy(text):
    win32clipboard.OpenClipboard()
    win32clipboard.EmptyClipboard()
    win32clipboard.SetClipboardText(text, win32clipboard.CF_UNICODETEXT)
    win32clipboard.CloseClipboard()
def paste():
    win32clipboard.OpenClipboard()
    data = win32clipboard.GetClipboardData(win32clipboard.CF_UNICODETEXT)
    win32clipboard.CloseClipboard()
    return data

if __name__ == "__main__":  
    text = "Testing\nthe “clip—board”: "
    try: text = text.decode('utf8')  # Python 2 needs decode to make a Unicode string.
    except AttributeError: pass
    print("%r" % text.encode('utf8'))
    copy(text)
    data = paste()
    print("%r" % data.encode('utf8'))
    print("OK" if text == data else "FAIL")

    try: print(data)
    except UnicodeEncodeError as er:
        print(er)
        print(data.encode('utf8'))

протестировано OK в Python 3.4 на Windows 8.1 и Python 2.7 на Windows 7. Также при чтении данных Unicode с помощью Unix linefeed, скопированных из Windows. Скопированные данные остаются в буфере обмена после выхода Python:"Testing the “clip—board”: "

если вы не хотите никаких внешних зависимостей, используйте этот код (теперь часть кросс-платформенной pyperclip -C:\Python34\Scripts\pip install --upgrade pyperclip):

def copy(text):
    GMEM_DDESHARE = 0x2000
    CF_UNICODETEXT = 13
    d = ctypes.windll # cdll expects 4 more bytes in user32.OpenClipboard(None)
    try:  # Python 2
        if not isinstance(text, unicode):
            text = text.decode('mbcs')
    except NameError:
        if not isinstance(text, str):
            text = text.decode('mbcs')
    d.user32.OpenClipboard(0)
    d.user32.EmptyClipboard()
    hCd = d.kernel32.GlobalAlloc(GMEM_DDESHARE, len(text.encode('utf-16-le')) + 2)
    pchData = d.kernel32.GlobalLock(hCd)
    ctypes.cdll.msvcrt.wcscpy(ctypes.c_wchar_p(pchData), text)
    d.kernel32.GlobalUnlock(hCd)
    d.user32.SetClipboardData(CF_UNICODETEXT, hCd)
    d.user32.CloseClipboard()

def paste():
    CF_UNICODETEXT = 13
    d = ctypes.windll
    d.user32.OpenClipboard(0)
    handle = d.user32.GetClipboardData(CF_UNICODETEXT)
    text = ctypes.c_wchar_p(handle).value
    d.user32.CloseClipboard()
    return text

самый простой способ-с pyperclip. Работает в python 2 и 3.

чтобы установить эту библиотеку, используйте:

pip install pyperclip

пример использования:

import pyperclip

pyperclip.copy("your string")

Если вы хотите получить содержимое буфера обмена:

clipboard_content = pyperclip.paste()

виджеты также имеют метод с именем .clipboard_get() что возвращает содержимое буфера обмена (если какая-то ошибка происходит на основе типа данных в буфере обмена).

The clipboard_get() метод упоминается в этом отчете об ошибке:
http://bugs.python.org/issue14777

Я думаю, что есть гораздо более простое решение для этого.

name = input('What is your name? ')
print('Hello %s' % (name) )

затем запустите программу в командной строке

python greeter.py / клип

это будет передавать вывод вашего файла в буфер обмена

import wx

def ctc(text):

    if not wx.TheClipboard.IsOpened():
        wx.TheClipboard.Open()
        data = wx.TextDataObject()
        data.SetText(text)
        wx.TheClipboard.SetData(data)
    wx.TheClipboard.Close()

ctc(text)

фрагмент кода для копирования буфера обмена:

создайте код Python оболочки в модуле с именем (clipboard.py):

import clr
clr.AddReference('System.Windows.Forms')
from System.Windows.Forms import Clipboard
def setText(text):
    Clipboard.SetText(text)

def getText():
    return Clipboard.GetText()

затем импортировать этот модуль в свой код.

import io
import clipboard
code = clipboard.getText()
print code
code = "abcd"
clipboard.setText(code)

Я должен отдать должное посту в блоге доступ к буферу обмена в IronPython.

это улучшенный ответ распылитель.

примечание 2 звонки update() и 200 ms задержки между ними. Они защищают замораживание приложений из-за нестабильного состояния буфера обмена:

from Tkinter import Tk
impor time

r = Tk()
r.withdraw()
r.clipboard_clear()
r.clipboard_append('some string')

r.update()
time.sleep(.2)
r.update()

r.destroy()

вы можете попробовать это:

command = 'echo content |clip'
subprocess.check_call(command, shell=True)
from Tkinter import Tk
clip = Tk()