¿Cómo copio una cadena al portapapeles en Windows usando Python?

Estoy intentando crear una aplicación básica de Windows que genere una cadena a partir de la entrada del usuario y luego la agregue al portapapeles. ¿Cómo copio una cadena en el portapapeles usando Python?

En realidad, pywin32 y ctypes parecen ser una exageración para esta tarea simple. Tkinter es un marco de GUI multiplataforma, que se incluye con Python de forma predeterminada y tiene métodos de acceso al portapapeles junto con otras cosas interesantes.

Si todo lo que necesita es poner texto en el portapapeles del sistema, esto lo hará:

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

Y eso es todo, no hay necesidad de meterse con bibliotecas de terceros específicas de la plataforma.

Si está utilizando Python 3, reemplace TKinter con tkinter .

No tenía una solución, solo una solución.

Windows Vista en adelante tiene un comando incorporado llamado clip que toma la salida de un comando desde la línea de comandos y lo coloca en el portapapeles. Por ejemplo, ipconfig | clip ipconfig | clip

Así que hice una función con el módulo os que toma una cadena y la agrega al portapapeles utilizando la solución de Windows incorporada.

 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. 

Sin embargo, como se señaló anteriormente en los comentarios, una desventaja de este enfoque es que el comando echo agrega automáticamente una nueva línea al final de su texto. Para evitar esto puedes usar una versión modificada del comando:

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

Si está utilizando Windows XP, funcionará siguiendo los pasos en Copiar y pegar desde el símbolo del sistema de Windows XP Pro directamente al Portapapeles .

También puede usar ctypes para acceder a la API de Windows y evitar el enorme paquete pywin32. Esto es lo que uso (disculpe el estilo pobre, pero la idea está ahí):

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

Puede utilizar pyperclip – módulo portapapeles multiplataforma. O Xerox – módulo similar, excepto que requiere que el módulo Python de win32 funcione en Windows.

Puede usar los excelentes pandas, que tienen un soporte integrado en el portapapeles, pero necesita pasar a través de un DataFrame.

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

Parece que necesitas agregar win32clipboard a tus paquetes de sitio. Es parte del paquete pywin32

Por alguna razón, nunca he podido conseguir que la solución Tk funcione para mí. La solución de kapace es mucho más viable, pero el formato es contrario a mi estilo y no funciona con Unicode. Aquí hay una versión modificada.

 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 

Lo anterior ha cambiado desde que se creó esta respuesta, para manejar mejor los caracteres extendidos de Unicode y Python 3. Se probó en Python 2.7 y 3.5, y funciona incluso con emoji como \U0001f601 (😁) .

He probado varias soluciones, pero esta es la más simple que pasa mi prueba :

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

Probado OK en Python 3.4 en Windows 8.1 y Python 2.7 en Windows 7. También cuando se leen datos Unicode con lineamientos Unix copiados desde Windows. Los datos copiados permanecen en el portapapeles después de que Python sale: "Testing the “clip—board”: 📋"

Si no desea dependencias externas, use este código (ahora parte de pyperclip multiplataforma – 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 

La forma más sencilla es con el chip de contacto . Trabajos en python 2 y 3.

Para instalar esta biblioteca, use:

 pip install pyperclip 

Ejemplo de uso:

 import pyperclip pyperclip.copy("your string") 

Si desea obtener los contenidos del portapapeles:

 clipboard_content = pyperclip.paste() 

Los widgets también tienen un método llamado .clipboard_get() que devuelve el contenido del portapapeles (a menos que ocurra algún tipo de error según el tipo de datos en el portapapeles).

El método clipboard_get() se menciona en este informe de error:
http://bugs.python.org/issue14777

Curiosamente, este método no se mencionó en las fonts de documentación TkInter en línea comunes (pero no oficiales) a las que generalmente me refiero.

Creo que hay una solución mucho más simple para esto.

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

Luego ejecuta tu progtwig en la línea de comando

python greeter.py | acortar

Esto canalizará la salida de su archivo al portapapeles.

 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) 

El fragmento que comparto aquí aprovecha la posibilidad de formatear archivos de texto: ¿qué sucede si desea copiar una salida compleja al portapapeles? (Diga una matriz numpy en la columna o una lista de algo)

 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 

Funciona solo para windows, se puede adaptar para linux o mac supongo. Tal vez un poco complicado ...

ejemplo:

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

Ctrl + V en cualquier editor de texto:

 ET phone home 

Fragmento de código para copiar el portapapeles:

Cree un código de Python de envoltorio en un módulo llamado ( 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() 

Luego importa el módulo anterior en tu código.

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

Debo dar crédito a la entrada del blog Clipboard Access en IronPython .

Esta es la respuesta mejorada del atomizador .

Nota 2 llamadas de update() y 200 ms retraso entre ellas. Protegen las aplicaciones de congelación debido a un estado inestable del portapapeles:

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

puedes probar esto

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