如何使用Python在Windows上将字符串复制到剪贴板?


193

我正在尝试制作一个基本的Windows应用程序,该应用程序从用户输入中构建一个字符串,然后将其添加到剪贴板。如何使用Python将字符串复制到剪贴板?



jaraco.clipboard做到了(太)了:剪贴板。复制(变量)
JinSnow

另请参阅我对有关使用Tkinter复制到剪贴板而不显示窗口的相关问题的回答。它包含一个Python函数,该函数使用Tkinter替换/返回剪贴板文本。
爱德华

Answers:


285

其实,pywin32并且ctypes似乎是这个简单的任务矫枉过正。Tkinter是一个跨平台的GUI框架,默认情况下随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,请替换TKintertkinter


55
结果= r.selection_get(选择= “剪贴板”):获取剪贴板内容
MJ

34
@SurDin Tkinter在python 3中被重命名为tkinter,因此这取决于您使用的版本。
诚实的安倍晋三

24
使用此功能粘贴剪贴板的内容后,我所有的应用程序都没有响应,奇怪的是,获得的结果效果很好。
Bartlomiej Lewandowski

14
如果我不打电话的话可以用r.destroy()。致电后,剪贴板将变为空,按Ctrl-V可能会导致目标应用冻结。(作业系统:Windows 7 x64)
netvope

8
对我来说,这不适用于python 3.4,但适用于python 2.7(是的,使用tkinter代替Tkinter)
Matty 2015年

78

我没有解决方案,只是一种解决方法。

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的命令提示符直接复制并粘贴到剪贴板中的步骤进行操作


20
如果text包含会| calc.exe 怎样?
Willi Ballenthin

2
@WilliBallenthin,那么您需要将其用双引号引起来。但是,如果包含双引号怎么办?然后,您需要将双引号加倍。 text with " quotes and | pipe成为"text with "" quotes and | pipe" 尽管这可能比95较旧的Windows系统上的问题
ColBeseder

5
功能极其不安全...发送到剪贴板的内容现在是入口矢量,从而增加了攻击面。
Phil L.

2
我还需要换行符支持,因此我将其修改为使用type。我将文本写入文件,并使用命令type myfile.txt | clip
Mixopteryx

1
尽管这是对我最好的答案,但是它有一个问题(Python 3.5,Windows 10);多余的换行符总是添加在字符串的末尾。如何避免呢?
mmj

42

您还可以使用ctypes进入Windows API并避免使用大量的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()

5
至少在python 2.6 x64中,我不得不更改bytes(data,"ascii")bytes(data)。感谢您回答这个问题,我不能使用pywin32或tk或许多其他东西,并且可以使用。
Pat Corwin

1
不用担心,但是请注意,从剪贴板返回的数据实际上是另一种编码,我相信它是Windows CP-1252。这一点被一起砍掉了,但是如果您使用的编码不正确,则非ASCII字符将引发错误或解码错误。
kapace

变量名不需要注释,所有内容都应支持Unicode。
Cees Timmerman 2014年

bytes(data, "mbcs")将使用Windows默认编码。请允许我将其加载到剪贴板"másreas ç saod é í ó u* ü ö ï/"并正确阅读。
mvbentes

1
使用mbcs给了我这个:OSError:异常:访问冲突写入0x0000000000000000
Seaky Lone

35

您可以使用pyperclip-跨平台剪贴板模块。或Xerox-类似的模块,但需要win32 Python模块才能在Windows上运行。


pyperclip在Windows上不执行Unicode。win32clipboard做。
Cees Timmerman 2014年

13
我的pyperclip补丁已被接受;c:\python34\Scripts\pip install --upgrade pyperclip处理Unicode文本。
Cees Timmerman 2014年

1
我花了一段时间才发现这pyperclip不是paperclip。此外,与2016年一样,pyperclip也可以使用Unicode字符。我已经测试了字符±°©©αβγθΔΨΦåäö可以在Win10 64位,Python 3.5和pyperclip 1.5.27上工作。
np8

28

您可以使用出色的熊猫,它具有内置的剪贴板支持,但是您需要通过DataFrame。

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

3
+1。我喜欢这个解决方案。它比公认的Tkinter解决方案还要简单。无论如何,如果您导入了熊猫,都不会产生额外的开销。它还适用于所有平台。在大多数情况下,它甚至不需要安装新的软件包。
ChaimG '17

4
pyperclip无论如何,都可以使用它,因此更好地使用pyperpclip
maxbellec

1
对于大多数人(即我)而言,pandas它随时可用,但import pyperclip不起作用。因此,我不同意“更好地使用pyperclip”。
核心医生

1
如果仅限使用熊猫,则可以直接使用pyperclip import pandas.io.clipboard as pyperclip或随意命名。那就是它所在的地方pandas,至少
David Culbreth

1
这似乎在您复制的字符串中添加了换行符
Gijs van Oort,

18

最简单的方法是使用pyperclip。适用于python 2和3。

要安装此库,请使用:

pip install pyperclip

用法示例:

import pyperclip

pyperclip.copy("your string")

如果要获取剪贴板的内容:

clipboard_content = pyperclip.paste()

3
pyperclip模块是否随Python一起提供?哪个版本?我在Python 2.7
中看

8
是的,否决一个可以在不到5行的时间内轻松解决问题的答案;因为像引用这样的细微细节更为重要;我朋友很好用stackoverflow。无论如何,我都会编辑nitpickers。给您的提示:否决无用或无法解决问题的答案;解决问题或至少是有用的答案是有用的,并在评论中提出建议以改善有用的答案,而不是反对。
maviz

2
没有参考,您什么都解决不了。但是,既然您添加了链接,由于答案现在是正确的,所以我将删除downvote。我更大的问题是它看起来像是标准库的导入。它看起来像可以复制/粘贴的代码。
Gloweye

pyperclip.paste()不适用于图片,只会返回NoneType错误。但可以右键单击并复制,然后使用python粘贴复制的结果。
JayRizzo

11

我尝试了各种解决方案,但这是通过我的测试的最简单的解决方案:

#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'))

在Windows 8.1上的Python 3.4和Windows 7上的Python 2.7中都经过了测试,还可以使用从Windows复制的Unix换行符读取Unicode数据。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

你去win32clipboard哪儿?它不是我的Python 2.7的一部分。为什么paste使用CF_TEXT代替CF_UNICODETEXT
Mark Ransom 2014年

@MarkRansom pywin32,因为我的测试工作正常,直到我使用hard使其更难为止。我已经更新了代码。
Cees Timmerman 2014年

11

由于某些原因,我一直无法获得Tk解决方案来为我工作。kapace的解决方案更可行,但是格式与我的风格相反,并且不适用于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'\0')
    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

自从首次创建此答案以来,上述内容已经发生了变化,以便更好地应对扩展的Unicode字符和Python3。它已经在Python 2.7和3.5中进行了测试,甚至可以与表情符号一起使用\U0001f601 (😁)


@CeesTimmerman我很想拥有Windows 8.1系统来测试原因。我可能有机会在今天晚些时候进行调查。您确定剪贴板中有文字吗?
Mark Ransom 2014年

是。在过去的三天内,我已经在Python中对剪贴板代码进行了广泛的测试。
Cees Timmerman 2014年

put()功能还需要工作;表情符号“📋”(\ U0001f400)复制为“🐀”(\ U0001f4cb)或“📋”。变成“📋”。
Cees Timmerman 2014年

@CeesTimmerman对此进行了说明。内部Unicode表示已更改,我不记得它是3.3还是3.4。要解决此问题,需要对UTF-16进行显式编码。这不是错误。
Mark Ransom 2014年

1
@YngvarKristiansen我终于可以进行这些更改了。我现在有信心,此代码可用于大多数现代版本的Python和每个可能的Unicode字符。
Mark Ransom


5

您可以使用module clipboard。它简单易用。适用于MacWindowsLinux
注意:它的替代pyperclip

安装后,将其导入:

import clipboard

然后,您可以像这样复制:

clipboard.copy("This is copied")

您还可以粘贴复制的文本:

clipboard.paste()

2
这似乎是最好的解决方案。剪贴板可以与一起安装pip install clipboard
vy32

5

这是我找到的最简单,最可靠的方法,如果您还可以,取决于熊猫。但是,我认为这并不是Pandas API的正式组成部分,因此它可能会在将来的更新中失效。从0.25.3开始

from pandas.io.clipboard import copy 
copy("test")

3

小部件还具有名为方法的方法.clipboard_get(),该方法返回剪贴板的内容(除非根据剪贴板中的数据类型发生某种错误)。

clipboard_get()错误报告中提到了该方法:http :
//bugs.python.org/issue14777

奇怪的是,这种方法在我通常参考的常见(但非官方)在线TkInter文档资源中并未提及。


3

我认为有一个更简单的解决方案。

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

然后在命令行中运行程序

python greeter.py | 夹

这会将文件的输出通过管道传输到剪贴板


这是一个很好的解决方案,但我想了很多蟒蛇的开发,并在IDE中运行
杰西·礼萨Khorasanee

2

除了Mark Ransom使用ctypes 的答案之外:这不适用于(所有?)x64系统,因为句柄似乎被截断为int大小。显式定义args和返回值有助于克服此问题。

import ctypes
import ctypes.wintypes as w

CF_UNICODETEXT = 13

u32 = ctypes.WinDLL('user32')
k32 = ctypes.WinDLL('kernel32')

OpenClipboard = u32.OpenClipboard
OpenClipboard.argtypes = w.HWND,
OpenClipboard.restype = w.BOOL

GetClipboardData = u32.GetClipboardData
GetClipboardData.argtypes = w.UINT,
GetClipboardData.restype = w.HANDLE

EmptyClipboard = u32.EmptyClipboard
EmptyClipboard.restype = w.BOOL

SetClipboardData = u32.SetClipboardData
SetClipboardData.argtypes = w.UINT, w.HANDLE,
SetClipboardData.restype = w.HANDLE

CloseClipboard = u32.CloseClipboard
CloseClipboard.argtypes = None
CloseClipboard.restype = w.BOOL

GHND = 0x0042

GlobalAlloc = k32.GlobalAlloc
GlobalAlloc.argtypes = w.UINT, w.ctypes.c_size_t,
GlobalAlloc.restype = w.HGLOBAL

GlobalLock = k32.GlobalLock
GlobalLock.argtypes = w.HGLOBAL,
GlobalLock.restype = w.LPVOID

GlobalUnlock = k32.GlobalUnlock
GlobalUnlock.argtypes = w.HGLOBAL,
GlobalUnlock.restype = w.BOOL

GlobalSize = k32.GlobalSize
GlobalSize.argtypes = w.HGLOBAL,
GlobalSize.restype = w.ctypes.c_size_t

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'\0')
    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(GHND, len(data) + 2)
    pcontents = GlobalLock(handle)
    ctypes.memmove(pcontents, data, len(data))
    GlobalUnlock(handle)
    SetClipboardData(CF_UNICODETEXT, handle)
    CloseClipboard()

#Test run
paste = get
copy = put
copy("Hello World!")
print(paste())

0
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)

2
对问题和解决方案进行解释将很有帮助。
showdev 2015年

将文本复制到剪贴板的功能。使用wx python库(我从没学过TK)来解决这里提出的问题。
jlk

随意编辑答案以包括对问题/解决方案的解释@jlk-这样做通常会使答案更有用。另外,感谢您的尝试,但是我想原始的发布者有一些理由专门要求Tk。
icedwater

0

我在这里共享的代码片段利用了格式化文本文件的功能:如果要将复杂的输出复制到剪贴板怎么办?(在列或某物列表中说一个numpy数组)

import subprocess
import os

def cp2clip(clist):

    #create a temporary file
    fi=open("thisTextfileShouldNotExist.txt","w")

    #write in the text file the way you want your data to be
    for m in clist:
        fi.write(m+"\n")

    #close the file
    fi.close()

    #send "clip < file" to the shell
    cmd="clip < thisTextfileShouldNotExist.txt"
    w = subprocess.check_call(cmd,shell=True)

    #delete the temporary text file
    os.remove("thisTextfileShouldNotExist.txt")

    return w

我猜想,它仅适用于Windows,可以适应linux或mac。也许有点复杂...

例:

>>>cp2clip(["ET","phone","home"])
>>>0

在任何文本编辑器中按Ctrl + V组合键:

ET
phone
home

0

这是雾化器的改进答案。

注意2呼叫update()200 ms它们之间的延迟。它们由于剪贴板的不稳定状态而保护冻结的应用程序:

from Tkinter import Tk
import time     

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

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

r.destroy()

0

使用python的剪贴板库!

import clipboard as cp
cp.copy("abc")

剪贴板现在包含“ abc”。粘贴愉快!


0

并非所有答案都适用于我的各种python配置,因此此解决方案仅使用subprocess模块​​。但是,copy_keyword必须是pbcopyMac或clipWindows:

import subprocess
subprocess.run('copy_keyword', universal_newlines=True, input='New Clipboard Value 😀')

以下是一些更广泛的代码,它们可以自动检查当前操作系统是什么:

import platform
import subprocess

copy_string = 'New Clipboard Value 😀'

# Check which operating system is running to get the correct copying keyword.
if platform.system() == 'Darwin':
    copy_keyword = 'pbcopy'
elif platform.system() == 'Windows':
    copy_keyword = 'clip'

subprocess.run(copy_keyword, universal_newlines=True, input=copy_string)

当您尝试粘贴该字符串时,IDLE崩溃。
Max Do Stuff

@MaxDoesStuff尝试不使用表情符号。我不知道为什么在默认IDLE中不起作用,但在其他IDLE中它起作用。
Fetchinator7

0

您可以使用winclip32模块!安装:

pip install winclip32

复制:

import winclip32
winclip32.set_clipboard_data(winclip32.UNICODE_STD_TEXT, "some text")

要得到:

import winclip32
print(winclip32.get_clipboard_data(winclip32.UNICODE_STD_TEXT))

有关更多信息:https : //pypi.org/project/winclip32/


-1

复制剪贴板的代码段:

在名为(剪贴板.py)的模块中创建包装Python代码:

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中的博客文章Clipboard Access


-2

您可以尝试以下方法:

command = 'echo content |clip'
subprocess.check_call(command, shell=True)

-9
from Tkinter import Tk
clip = Tk()

也许您可以建设性地告诉您所收到的错误消息以及所使用的python版本。我写的2行适用于
python2

2
问题是“如何使用Python在Windows上将字符串复制到剪贴板”。当然,这不会崩溃,但是它对问题完全没有满足,因为它实际上 什么都不做
Antti Haapala 2015年

2
问:如何使用Python将字符串复制到Windows剪贴板?答:导入GUI库并创建根对象。。抱歉,这如何回答所陈述的问题?
马丁·皮特斯

使用python3,您可以按照以下步骤进行操作:import tkinter> tki = tkinter.Tk()> tki.clipboard_clear()#清除当前剪贴板> mystring ='Hello World'> tki.clipboard_append(mystring)> tki.clipboard_get( )Out [19]:'Hello World'>
tagoma

2
然后做出答案。就目前而言,您实际上没有任何帮助。您在Windows上测试过吗?
马丁·彼得斯
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.