ฉันกำลังพยายามสร้างแอปพลิเคชัน Windows ขั้นพื้นฐานที่สร้างสตริงจากการป้อนข้อมูลผู้ใช้แล้วเพิ่มลงในคลิปบอร์ด ฉันจะคัดลอกสตริงไปยังคลิปบอร์ดโดยใช้ Python ได้อย่างไร
ฉันกำลังพยายามสร้างแอปพลิเคชัน Windows ขั้นพื้นฐานที่สร้างสตริงจากการป้อนข้อมูลผู้ใช้แล้วเพิ่มลงในคลิปบอร์ด ฉันจะคัดลอกสตริงไปยังคลิปบอร์ดโดยใช้ Python ได้อย่างไร
คำตอบ:
ที่จริงpywin32
และctypes
ดูเหมือนจะเป็น overkill สำหรับงานนี้ง่าย 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()
และนั่นคือทั้งหมดที่คุณไม่จำเป็นต้องยุ่งกับไลบรารีของบุคคลที่สามเฉพาะแพลตฟอร์ม
หากคุณกำลังใช้งูหลาม 3 แทนที่ด้วยTKinter
tkinter
r.destroy()
มันทำงานได้ถ้าผมไม่ได้โทร เมื่อฉันเรียกสิ่งนั้นแล้วคลิปบอร์ดจะว่างเปล่าและการกด Ctrl-V อาจทำให้แอปเป้าหมายหยุดทำงาน (ระบบปฏิบัติการ: Windows 7 x64)
ฉันไม่มีวิธีแก้ปัญหา แต่เป็นวิธีแก้ปัญหา
Windows Vista เป็นต้นไปมีคำสั่ง inbuilt ที่เรียกclip
ใช้เอาท์พุทของคำสั่งจากบรรทัดคำสั่งและวางไว้ในคลิปบอร์ด ตัวอย่างเช่นipconfig | clip
.
ดังนั้นฉันจึงสร้างฟังก์ชั่นด้วยos
โมดูลที่ใช้สตริงและเพิ่มไปยังคลิปบอร์ดโดยใช้วิธีการแก้ปัญหาของ Windows inbuilt
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 ของคำสั่งตรงพรอมต์ไปยังคลิปบอร์ด
text
มี| calc.exe
?
text with " quotes and | pipe
กลายเป็น"text with "" quotes and | pipe"
แม้ว่านี้อาจมีปัญหาเกี่ยวกับระบบที่มีหน้าต่างที่มีอายุมากกว่า 95
type
ฉันยังต้องการการสนับสนุนสำหรับการขึ้นบรรทัดใหม่ดังนั้นผมจึงมีการปรับเปลี่ยนนี้ในการใช้งาน type myfile.txt | clip
ผมเขียนข้อความของฉันไปยังแฟ้มและใช้คำสั่ง
คุณยังสามารถใช้ 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()
bytes(data,"ascii")
bytes(data)
ขอบคุณที่ตอบคำถามฉันไม่สามารถใช้ pywin32 หรือ tk หรือสิ่งอื่น ๆ อีกมากมายและใช้งานได้
bytes(data, "mbcs")
จะทำงานร่วมกับการเข้ารหัสค่าเริ่มต้นของ windows อนุญาตให้ฉันโหลดสิ่งนี้ไปยังคลิปบอร์ด"másreas ç saod é í ó u* ü ö ï/"
และอ่านอย่างถูกต้อง
คุณสามารถใช้pyperclip - โมดูลคลิปบอร์ดข้ามแพลตฟอร์ม หรือXerox - โมดูลที่คล้ายกันยกเว้นต้องใช้โมดูล win32 Python เพื่อทำงานบน Windows
pyperclip
ไม่ทำ Unicode บน Windows win32clipboard
ทำ.
pyperclip
แพทช์ของฉันได้รับการยอมรับ; c:\python34\Scripts\pip install --upgrade pyperclip
เพื่อจัดการข้อความ Unicode
pyperclip
paperclip
นอกจากนี้ในปี 2559 pyperclip ยังทำงานกับอักขระ Unicode ด้วย ฉันได้ทดสอบตัวละคร±°©ฟรานซ์αäåäöเพื่อทำงานบน Win10 64 บิตด้วย Python 3.5 และ pyperclip 1.5.27
คุณสามารถใช้แพนด้าที่ยอดเยี่ยมซึ่งมีการสนับสนุนคลิปบอร์ดในตัว แต่คุณต้องผ่าน DataFrame
import pandas as pd
df=pd.DataFrame(['Text to copy'])
df.to_clipboard(index=False,header=False)
pyperclip
อยู่ดีกว่าจึงใช้งานได้ดีกว่าpyperpclip
pandas
พร้อมใช้งาน แต่import pyperclip
ไม่ทำงาน ดังนั้นฉันจึงไม่เห็นด้วยกับ "better use pyperclip"
import pandas.io.clipboard as pyperclip
หรือตั้งชื่อตามที่คุณต้องการ นั่นคือสิ่งที่มันนั่งอยู่ภายในpandas
อย่างน้อย
วิธีที่ง่ายที่สุดคือมีpyperclip ทำงานได้ในหลาม 2 และ 3
ในการติดตั้งไลบรารีนี้ให้ใช้:
pip install pyperclip
ตัวอย่างการใช้งาน:
import pyperclip
pyperclip.copy("your string")
หากคุณต้องการได้รับเนื้อหาของคลิปบอร์ด:
clipboard_content = pyperclip.paste()
pyperclip
โมดูลมาพร้อมกับ Python หรือไม่ เวอร์ชันไหน ฉันไม่เห็นมันใน Python 2.7 ...
pyperclip.paste()
ใช้งานไม่ได้กับรูปภาพที่เพิ่งคืนค่าNoneType
ข้อผิดพลาด แต่ทำงานได้ด้วยคลิกขวาแล้วคัดลอกจากนั้นใช้ python เพื่อวางผลลัพธ์ที่คัดลอก
ฉันได้ลองวิธีแก้ปัญหาต่าง ๆ แล้ว แต่นี่เป็นวิธีที่ง่ายที่สุดที่ผ่านการทดสอบของฉัน :
#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'))
ทดสอบตกลงใน Python 3.4 บน Windows 8.1 และ Python 2.7 บน Windows 7 นอกจากนี้เมื่ออ่านข้อมูล Unicode ด้วย Unix linefeeds คัดลอกมาจาก Windows ข้อมูลที่คัดลอกจะยังคงอยู่บนคลิปบอร์ดหลังจากออกจาก 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
?
ด้วยเหตุผลบางอย่างฉันจึงไม่สามารถใช้ Tk solution ให้ฉันได้ วิธีแก้ปัญหาของ kapaceนั้นใช้งานได้มากกว่า แต่การจัดรูปแบบนั้นขัดกับสไตล์ของฉัน นี่คือรุ่นที่แก้ไข
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 และ Python 3 มันได้รับการทดสอบทั้งใน Python 2.7 และ 3.5 \U0001f601 (😁)
และการทำงานแม้จะมีอีโมจิเช่น
put()
ฟังก์ชั่นนี้ยังต้องทำงาน; emoji "📋" (\ U0001f400) ถูกคัดลอกเป็น "🐀" (\ U0001f4cb) หรือ "📋" เปลี่ยนเป็น "📋"
ดูเหมือนว่าคุณจะต้องเพิ่ม win32clipboard ในแพ็คเกจเว็บไซต์ของคุณ มันเป็นส่วนหนึ่งของแพ็คเกจ pywin32
นี่เป็นวิธีที่ง่ายและน่าเชื่อถือที่สุดที่ฉันพบว่าคุณโอเคขึ้นอยู่กับนุ่น อย่างไรก็ตามฉันไม่คิดว่านี่เป็นส่วนหนึ่งของ Pandas API อย่างเป็นทางการดังนั้นมันอาจผิดพลาดกับการอัพเดทในอนาคต มันทำงานได้ตั้งแต่ 0.25.3
from pandas.io.clipboard import copy
copy("test")
clipboard
คุณสามารถใช้โมดูล มันง่ายและใช้งานง่ายมาก ทำงานร่วมกับMac , วินโดวส์และลินุกซ์
หมายเหตุ:มันเป็นทางเลือกของpyperclip
หลังจากติดตั้งนำเข้า:
import clipboard
จากนั้นคุณสามารถคัดลอกเช่นนี้:
clipboard.copy("This is copied")
คุณยังสามารถวางข้อความที่คัดลอก:
clipboard.paste()
pip install clipboard
คลิปบอร์ดสามารถติดตั้งได้กับ
วิดเจ็ตยังมีเมธอด.clipboard_get()
ที่ส่งคืนเนื้อหาของคลิปบอร์ด (ยกเว้นว่ามีข้อผิดพลาดเกิดขึ้นตามประเภทของข้อมูลในคลิปบอร์ด)
clipboard_get()
วิธีการที่กล่าวถึงในรายงานข้อผิดพลาดนี้:
http://bugs.python.org/issue14777
น่าแปลกที่วิธีนี้ไม่ได้กล่าวถึงในแหล่งข้อมูลเอกสาร TkInter ออนไลน์ (แต่ไม่เป็นทางการ) ทั่วไปที่ฉันมักจะอ้างถึง
ฉันคิดว่ามีวิธีแก้ปัญหาที่ง่ายกว่านี้มาก
name = input('What is your name? ')
print('Hello %s' % (name) )
จากนั้นรันโปรแกรมของคุณในบรรทัดคำสั่ง
python greeter.py | คลิป
สิ่งนี้จะไปป์เอาท์พุทไฟล์ของคุณไปยังคลิปบอร์ด
นอกจากคำตอบของ 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())
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)
ตัวอย่างที่ฉันแบ่งปันที่นี่ใช้ประโยชน์จากความสามารถในการจัดรูปแบบไฟล์ข้อความ: ถ้าคุณต้องการคัดลอกเอาต์พุตที่ซับซ้อนไปยังคลิปบอร์ด (พูดอาร์เรย์ 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
นี่คือคำตอบที่ดีขึ้นของเครื่องฉีดน้ำ
หมายเหตุ 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()
ใช้ไลบรารี่ของ python!
import clipboard as cp
cp.copy("abc")
คลิปบอร์ดมี 'abc' อยู่ในขณะนี้ การวางอย่างมีความสุข!
ไม่ใช่คำตอบทั้งหมดที่ใช้งานได้กับการกำหนดค่าหลามแบบต่างๆของฉันดังนั้นโซลูชันนี้ใช้โมดูลย่อยเท่านั้น อย่างไรก็ตามcopy_keyword
ต้องpbcopy
สำหรับ Mac หรือclip
Windows:
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 ได้! ติดตั้ง:
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/
ข้อมูลโค้ดเพื่อคัดลอกคลิปบอร์ด:
สร้างรหัส Python สำหรับ wrapper ในโมดูลชื่อ ( 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()
จากนั้นนำเข้าโมดูลข้างต้นลงในรหัสของคุณ
import io
import clipboard
code = clipboard.getText()
print code
code = "abcd"
clipboard.setText(code)
ผมต้องให้เครดิตกับบล็อกโพสต์คลิปบอร์ดเข้าถึงใน IronPython
คุณสามารถลองสิ่งนี้:
command = 'echo content |clip'
subprocess.check_call(command, shell=True)
from Tkinter import Tk
clip = Tk()