web-dev-qa-db-fra.com

Comment copier une chaîne dans le presse-papiers sous Windows en utilisant Python?

J'essaie de créer une application Windows de base qui crée une chaîne à partir de la saisie de l'utilisateur, puis l'ajoute au presse-papiers. Comment copier une chaîne dans le presse-papiers en utilisant Python?

164
tester

Réellement, pywin32 et ctypes semblent exagérés pour cette tâche simple. Tkinter est un framework d'interface graphique multi-plateforme, livré avec Python par défaut et disposant de méthodes d'accès au presse-papiers ainsi que d'autres éléments intéressants.

Si tout ce dont vous avez besoin est de mettre du texte dans le presse-papiers du système, vous y arriverez:

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

Et c'est tout, pas besoin de perdre son temps avec les bibliothèques tierces spécifiques à la plate-forme.

Si vous utilisez Python 3, remplacez TKinter par tkinter.

255
atomizer

Je n'avais pas de solution, juste une solution de contournement.

Windows Vista et les versions ultérieures ont une commande intégrée appelée clip qui extrait le résultat d’une commande à partir de la ligne de commande et le place dans le presse-papiers. Par exemple, ipconfig | clip.

J'ai donc créé une fonction avec le module os qui prend une chaîne et l'ajoute au presse-papiers à l'aide de la solution Windows intégrée.

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.

Comme indiqué précédemment dans les commentaires, toutefois, l'un des inconvénients de cette approche est que la commande echo ajoute automatiquement une nouvelle ligne à la fin de votre texte. Pour éviter cela, vous pouvez utiliser une version modifiée de la commande:

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

Si vous utilisez Windows XP, cela fonctionnera simplement en suivant les étapes décrites dans copier et coller depuis Windows XP Pro directement dans le Presse-papiers.

74
user1227883

Vous pouvez également utiliser ctypes pour accéder à l'API Windows et éviter le package Pywin32. C'est ce que j'utilise (excusez le style médiocre, mais l'idée est là):

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

Vous pouvez utiliser pyperclip - module de presse-papiers multiplate-forme. Ou Xerox - module similaire, sauf que le module win32 Python fonctionne sous Windows .

27
pongo

Vous pouvez utiliser les excellents pandas, qui ont un support de presse-papiers intégré, mais vous devez passer par un DataFrame.

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

Pour une raison quelconque, je n'ai jamais réussi à faire en sorte que la solution Tk fonctionne pour moi. solution de kapace est beaucoup plus pratique, mais la mise en forme est contraire à mon style et ne fonctionne pas avec Unicode. Voici une version modifiée.

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

Ce qui précède a changé depuis la création de cette réponse, afin de mieux gérer les caractères Unicode étendus et Python 3. Il a été testé à la fois Python 2.7 et 3.5 , et fonctionne même avec des emoji tels que \U0001f601 (????).

10
Mark Ransom

On dirait que vous devez ajouter win32clipboard à votre site-packages. Cela fait partie du paquet pywin32

10
Jason Coon

Le moyen le plus simple est d'utiliser pyperclip . Fonctionne dans python 2 et 3.

Pour installer cette bibliothèque, utilisez:

pip install pyperclip

Exemple d'utilisation:

import pyperclip

pyperclip.copy("your string")

Si vous voulez obtenir le contenu du presse-papiers:

clipboard_content = pyperclip.paste()
10
maviz

J'ai essayé diverses solutions, mais c'est la plus simple qui réussisse mon test :

#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 __== "__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'))

Testé OK dans Python 3.4 sous Windows 8.1 et Python 2.7 sous Windows 7. Également lors de la lecture de données Unicode avec des sauts de ligne Unix copiés à partir de Windows. Les données copiées restent sur le presse-papiers après Python quitte: "Testing the “clip—board”: ????"

Si vous ne voulez pas de dépendances externes, utilisez ce code (qui fait maintenant partie de la multiplate-forme 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
9
Cees Timmerman

Je pense qu'il existe une solution beaucoup plus simple à cela.

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

Puis lancez votre programme en ligne de commande

python greeter.py | agrafe

Cela dirigera la sortie de votre fichier vers le presse-papier

3
jdeyrup

Les widgets ont également une méthode nommée .clipboard_get() qui renvoie le contenu du presse-papiers (à moins qu'un type d'erreur ne se produise en fonction du type de données dans le presse-papiers).

La méthode clipboard_get() est mentionnée dans ce rapport de bogue:
http://bugs.python.org/issue14777

Étrangement, cette méthode n'était pas mentionnée dans les sources de documentation TkInter en ligne courantes (mais non officielles) auxquelles je me réfère habituellement.

3
mpb

Vous pouvez utiliser le module clipboard . C'est simple et extrêmement facile à utiliser. Fonctionne avec Mac , Windows , & Linux .
Note: C'est une alternative de pyperclip

Après l'installation, importez-le:

import clipboard

Ensuite, vous pouvez copier comme ceci:

clipboard.copy("This is copied")

Vous pouvez également coller le texte copié:

clipboard.paste()
1
Black Thunder

C'est la réponse améliorée de atomiseur.

Remarque 2 appels de update() et 200 ms délai entre eux. Ils protègent les applications de gel en raison d'un état instable du presse-papiers:

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()
0
MarianD
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)
0
jlk

L'extrait de code que je partage ici tire parti de la possibilité de formater des fichiers texte: que se passe-t-il si vous souhaitez copier une sortie complexe dans le Presse-papiers? (Dites un tableau numpy en colonne ou une liste de quelque chose)

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

ne fonctionne que pour les fenêtres, peut être adapté pour linux ou mac, je suppose. Peut-être un peu compliqué ...

exemple:

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

Ctrl + V dans n’importe quel éditeur de texte:

ET
phone
home
0
thomasJeanne