如何将字符串复制到剪贴板?

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

218267 次浏览

看起来您需要将win32clipboard添加到站点包中。它是pywin32包的一部分

你也可以使用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()

实际上,对于这个简单的任务,pywin32ctypes似乎是多余的。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,用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的命令提示符直接复制粘贴到剪贴板中的步骤就可以工作。

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

clipboard_get()方法在此错误报告中被提及 http://bugs.python.org/issue14777 < / p >

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

你可以使用< >强pyperclip < / >强 -跨平台剪贴板模块。或< >强施乐< / >强 -类似的模块,除了需要win32 Python模块才能在Windows上工作。

出于某种原因,我从来没有能够得到Tk解决方案为我工作。kapace的解决方案更可行,但格式与我的风格相反,它不能与Unicode兼容。这是修改后的版本。

import ctypes


from ctypes.wintypes import BOOL, HWND, HANDLE, HGLOBAL, UINT, LPVOID
from ctypes import c_size_t as SIZE_T


OpenClipboard = ctypes.windll.user32.OpenClipboard
OpenClipboard.argtypes = HWND,
OpenClipboard.restype = BOOL
EmptyClipboard = ctypes.windll.user32.EmptyClipboard
EmptyClipboard.restype = BOOL
GetClipboardData = ctypes.windll.user32.GetClipboardData
GetClipboardData.argtypes = UINT,
GetClipboardData.restype = HANDLE
SetClipboardData = ctypes.windll.user32.SetClipboardData
SetClipboardData.argtypes = UINT, HANDLE
SetClipboardData.restype = HANDLE
CloseClipboard = ctypes.windll.user32.CloseClipboard
CloseClipboard.restype = BOOL
CF_UNICODETEXT = 13


GlobalAlloc = ctypes.windll.kernel32.GlobalAlloc
GlobalAlloc.argtypes = UINT, SIZE_T
GlobalAlloc.restype = HGLOBAL
GlobalLock = ctypes.windll.kernel32.GlobalLock
GlobalLock.argtypes = HGLOBAL,
GlobalLock.restype = LPVOID
GlobalUnlock = ctypes.windll.kernel32.GlobalUnlock
GlobalUnlock.argtypes = HGLOBAL,
GlobalSize = ctypes.windll.kernel32.GlobalSize
GlobalSize.argtypes = HGLOBAL,
GlobalSize.restype = SIZE_T


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字符和Python 3。它已经在Python 2.7和3.5中进行了测试,甚至可以使用\U0001f601 (😁)这样的表情符号。

更新2021-10-26:这对我来说在Windows 7和Python 3.8中工作得很好。然后我买了一台Windows 10和Python 3.10的新电脑,它失败了,就像评论中指出的那样。这篇文章给了我答案。ctypes中的函数没有正确指定的参数和返回类型,并且默认值与64位值不一致。我修改了上面的代码,以包括缺失的信息。

我尝试了各种解决方案,但这是传递我的测试的最简单的一个:

#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中测试OK。同样,当使用从Windows复制的Unix换行符读取Unicode数据时。在Python退出后,复制的数据仍保留在剪贴板上:"Testing . “剪贴板”:📋“

.

如果你不想要外部依赖,使用下面的代码(现在是跨平台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
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)

复制剪贴板的代码片段:

在名为(clipboard.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中的剪贴板访问

你可以使用出色的pandas,它有一个内置的剪贴板支持,但你需要通过一个DataFrame。

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

我认为有一个更简单的解决办法。

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

然后在命令行中运行程序

Python greeting .py |剪辑

这将把文件的输出输出到剪贴板

这是雾化器的改进答案。

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

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

要安装这个库,请使用:

pip install pyperclip

使用示例:

import pyperclip


pyperclip.copy("your string")

如果你想获取剪贴板的内容:

clipboard_content = pyperclip.paste()

你可以试试这个:

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

我在这里分享的代码片段利用了格式化文本文件的功能:如果您想将复杂的输出复制到剪贴板,该怎么办?(比如一个列中的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

如果你不喜欢这个名字,你可以使用衍生模块clipboard

注:只是pyperclip的选择性包装

安装完成后,导入:

import clipboard

然后你可以像这样复制:

clipboard.copy("This is copied")

你也可以粘贴复制的文本:

clipboard.paste()

除了Mark Ransom的回答使用ctypes: 这并不适用于(所有?)x64系统,因为句柄似乎被截断为int-size。 显式定义参数和返回值有助于克服这个问题

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

这是我发现的最简单可靠的方法,如果你可以依赖熊猫。然而,我不认为这是熊猫API的官方部分,所以它可能会打破未来的更新。它的工作为0.25.3

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

使用python的剪贴板库!

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

剪贴板现在包含'abc'。粘贴快乐!

并不是所有的答案都适用于我的各种python配置,所以这个解决方案只使用subprocess模块。然而,对于Mac, copy_keyword必须是pbcopy,对于Windows, clip:

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)
你可以使用winclip32模块! 安装:< / p >
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/

使用pyperclip模块

使用pip pip install pyperclip安装。

复制文本"Hello World!"到剪贴板

import pyperclip
pyperclip.copy('Hello World!')

你可以在任何地方使用Ctrl+V来粘贴它。

使用python粘贴复制的文本

pyperclip.paste() # This returns the copied text of type <class 'str'>

在Windows上,你可以使用这个。没有外部依赖,也不必打开子进程:

import win32clipboard




def to_clipboard(txt):


win32clipboard.OpenClipboard()
win32clipboard.EmptyClipboard()
win32clipboard.SetClipboardText(txt)
win32clipboard.CloseClipboard()

你也可以用>clipboard

import clipboard


def copy(txt):
clipboard.copy(txt)
    

copy("your txt")

如果(仅当)应用程序已经使用了Qt,您可以使用这个(优点是没有额外的第三方依赖)

from PyQt5.QtWidgets import QApplication
clipboard = QApplication.clipboard()


# get text (if there's text inside instead of e.g. file)
clipboard.text()


# set text
clipboard.setText(s)

这要求已经构造了Qt应用程序对象,所以它不应该被使用,除非应用程序已经使用Qt。

此外,通常情况下,在X系统(可能还有其他系统)中,除非使用parcellite或xclipboard之类的东西,否则内容只会持续到应用程序存在为止。

文档:

参见:python - PyQT -复制文件到剪贴板-堆栈溢出

使用stdlib解决方案,没有安全问题

下面的解决方案在Linux中工作,不需要任何额外的库,也没有在shell中执行不需要的代码的风险。

import subprocess


def to_clipboard(text: str) -> None:
sp = subprocess.Popen(["xclip"], stdin=subprocess.PIPE,
stdout=subprocess.PIPE)
sp.communicate(text.encode("utf8"))

请注意,Linux中有多个剪贴板,一个是你用中鼠标(主)使用的,另一个是你按STRG+C,STRG+V使用的。

你可以通过添加一个选择参数,即["xclip", "-selection", "clipboard"]来定义使用哪个剪贴板。 有关详细信息,请参见man xclip

如果使用Windows,只需将xclip替换为剪辑

这个解决方案不需要Tkinter,它没有一些Python安装(即我目前使用的自定义构建)。