如何在Python中从Windows剪贴板读取文本?

152

如何使用Python从(Windows)剪贴板中读取文本?


5
关于这个问题的相关内容。 - glglgl
在我的情况下,只有dan的答案有效,他使用了clipboard包。 - Soorena
请注意,问题标题没有提供上下文,即这是Python和Windows特定的。 - Jason S
1
@JasonS 说得好。请注意,这个问题是在2008年网站刚刚成立时提出的,因此我还没有使用它很长时间。我认为我的理由是这些细节可以通过标签来捕捉。现在我已经编辑了标题,包含了这些细节。 - Foo42
同意,我加入于'08年12月,并记得早期的日子。现在普遍的观点似乎是从标题中消除上下文线索,依靠标签,但当您在Google或此网站上的“链接/相关”部分中找到StackOverflow内容时,您看到的仅是标题。总之,我的评论针对的远不只是你,而是针对SO整体的调节思维。 - Jason S
15个回答

149
你可以使用名为 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后不要将对象放置在剪贴板上。


8
你知道是否有一种使用 with 语句的方法吗? - Norfeldt
4
值得注意的是,在py34、win7中,如果没有先调用EmptyClipboard函数,SetClipboardText函数将无法正常工作。 - CoderTao
如果您想执行更复杂的操作,例如从剪贴板中获取HTML格式的内容,则此模块非常有用。请参见https://dev59.com/RnPYa4cB1Zd3GeqPmbmu - xji
2
@Norfeldt 如果没有原生的方法,你可以轻松地创建自己的自定义对象来支持“with”。 - Elijas Dapšauskas
如果我尝试使用以"""定义的字符串变量复制多行文本,则不起作用。 - Rodrigo Vieira

82

你可以通过内置的Tkinter模块轻松完成此操作,该模块基本上是一个GUI库。这段代码创建了一个空白部件,以从操作系统获取剪贴板内容。

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

3
在我看来,比起尝试安装pywin32(它有一系列已知的问题),这种方法要好得多。关于大小写差异的提示很好,一开始很难注意到。 - Adrian Larson
对我来说,这会创建一个令人沮丧的剩余Tk()窗口(并使用资源)。如果您只是偶尔这样做,可以通过添加几行代码来防止它:clipboard = a.clipboard_get(); a.destroy()``` - user2979044

61

我发现pyperclip是从Python中访问剪贴板最简单的方法:

  1. 安装pyperclip: pip install pyperclip

  2. 用法:

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

Pyperclip支持Windows、Linux和Mac,并且似乎也能处理非ASCII字符。 测试过的字符包括±°©©αβγθΔΨΦåäö


它适用于3.6吗?它已经成功安装,但是当使用paste()方法时,它会给我一个错误:“from PySide import version as PYSIDE_VERSION # analysis:ignore ModuleNotFoundError: No module named 'PySide'”。当我尝试安装Pyside时,它说不支持3.6。 - gaurav
是的,它应该在Python 3.6上运行,并且我刚刚使用Python 3.7.4(64位)进行了测试。查看软件包的setup.py,它不应该依赖于Pyside或任何其他软件包。您确定粘贴命令正在尝试使用Pyside吗? - Niko Pasanen
是的,粘贴命令正在寻找Pyside,由于Pyside只支持Python 3.4及以下版本,因此会出现错误。 - gaurav
这似乎是针对使用Python3.6的WSL最简单的解决方案。 - enoted
2
我使用pip安装了clipboard包,它只有一行代码from pyperclip import copy, paste,哈哈。pyperclib是完美的解决方案。 - Lê Quang Duy
3
pyperclip 不仅适用于 Windows,还支持 Mac 和 Linux,这很方便。 - David Foster

28

如果您不想安装额外的软件包,ctypes 也可以完成工作。

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

这在Windows 10上似乎不起作用。它总是打印“None”。 - Aran-Fey
只要我使用Python 32位,Windows 10 就能正常工作。我已更新答案,使其也适用于64位。 - kichik
在“text = ctypes.c_char_p(data_locked)”这一行上,出现了“expected char pointer, got int”的错误,你有什么想法吗? - txemsukr
1
看到类似的解决方案也能复制文本到剪贴板会很不错。 - mrkbutty
1
有关枚举可用剪贴板格式的任何提示?也许获取二进制/文件数据? - sytech

23

3
获取剪贴板值的代码(使用Tkinter):
from Tkinter import Tk [\nl] r = Tk() [\nl] result = r.selection_get(selection="CLIPBOARD") [\nl] r.destroy()
- mgkrebbs
这当然很容易,但它可能会暂时改变窗口焦点,导致窗口闪烁。如果可用的话,最好编写win32clipboard代码,否则可以回退到Tkinter。 - Keeely

14
上面获得最多赞的答案有些奇怪,它只是简单地清空剪贴板,然后获取内容(此时为空)。可以清空剪贴板以确保某些剪贴板内容类型(例如“格式化文本”)不会“覆盖”您要保存在剪贴板中的纯文本内容。

下面这段代码将剪贴板中所有的换行符替换为空格,然后删除所有双空格,最后将内容保存回剪贴板:
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()

12

Python标准库可以完成这个任务...

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

2
谢谢,这对我来说可行,而且不需要使用第三方软件包。 - jdhao
1
不错的解决方案。如果我们不需要Tk GUI,最好在某个地方使用root.quit() - kakyo

6
对于我的控制台程序,上述使用tkinter的答案并没有完全适用于我,因为.destroy()总是出现错误:
can't invoke "event" command: application has been destroyed while executing...
或者当使用.withdraw()时,控制台窗口没有获取焦点。
要解决这个问题,您还需要在.destroy()之前调用.update()。例如:
# Python 3
import tkinter

r = tkinter.Tk()
text = r.clipboard_get()
r.withdraw()
r.update()
r.destroy()
方法防止窗口在毫秒级别内显示,然后被销毁,将焦点返回给控制台。

4

使用Python库Clipboard

它的使用方法非常简单:

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

16
这本质上是使用pyperclip。这个模块的整个源代码就是:from pyperclip import copy, paste - pbreach
1
这是正确的。但他们说“clipboard”是更好的名称。这个函数应该被包含在Python标准库中。 - Vincenzooo
2
这种包就是耻辱...仅使用另一个包的一行代码。 - jdhao
1
import pyperclip as clipboard - John
@jdhao 如果你想一想的话,这也有点好笑...也许他们使用了pyperclip模块将一些代码复制到剪贴板中,以此来创建clipboard模块! - Andrew

3
import pandas as pd
df = pd.read_clipboard()

2
这对我来说最适合,因为我已经依赖于Pandas。其背后的实现存储在 pandas.io.clipboard.clipboard_get()中,如果您需要文本而无需解析它,则更有用。 - Yuval

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接