Bu python betiği neden% 100 CPU tüketen arka planda çalışıyor?


22

Arka planda panodan metin okuyan ve basan basit bir python betiği çalıştırmak istiyorum. İşte kodum.

#!/usr/bin/env python

import Tkinter

last_clipboard = ""

def get_clipboard():
  global last_clipboard
  root = Tkinter.Tk()
  root.withdraw() # Hide the main window (optional)
  text_in_clipboard = root.clipboard_get()
  if text_in_clipboard != last_clipboard:
    last_clipboard = text_in_clipboard
    print last_clipboard


while True:
  get_clipboard()

Bu beklendiği gibi çalışıyor ancak çok fazla CPU (% 100 CPU) tüketiyor.

Bu kadar fazla tüketmeden düzgün çalışmasını nasıl sağlayabilirim?


26
Kullandığınız çerçeve tarafından destekleniyorsa, panodaki bir döngü yerine değişiklikleri algılamak için olaya dayalı kod kullanın. Pano değişinceye kadar sürekli olarak almak veya sistemin değiştiğini söyleyen sistemi dinlemek arasında bir fark var.
stefan

6
@ tatlı hiç python içinde yapmadım, ama işte GTK ile bir çözüm gibi görünüyor: stackoverflow.com/a/25961646/985296 (herhangi bir platform bağımlılığından bahsetmiyor).
stefan

@ jpmc26 ve tatlı Bir meta tartışma gibi görünüyor, oraya almaktan çekinmeyin. Kapsam için bu temizliği için kesinlikle iyi bir fikir .
Direk

1
@dessert Siz ve JPMC bunun açık / kapalı konu olup olmadığını tartışmak istiyorsanız, bir meta konu açın. Lütfen bu argüman için yorum kullanmayın. (Yorum temizleme işlemi tamamlandı, konu Meta tartışmanızın yapılmasını beklemekle birlikte bir yorum için kilitlendi, ancak yorum tartışmalarını da durdurdu)
Thomas Ward

Yanıtlar:


44

Döngünün time.sleep()içinde unuttun, SO cevabınawhile göre, 0.2 saniye uyumak, sorgulama sıklığı ve CPU yükü arasında iyi bir uzlaşmadır:

import time

while True:
  get_clipboard()
  time.sleep(0.2) # sleep for 0.2 seconds

Panoyu 0,2 saniyede bir kontrol etmek kolayca sık görünüyor; daha az CPU yükü istiyorsanız bu değeri bile artırabilirsiniz - birkaç kullanıcı pano içeriğini bir saniyeden diğerine değiştirir.

Genel olarak bir döngü içinde sorgulamanın, sık sık iyi tasarım olarak kabul edilmediğini unutmayın. Pano içeriğinin değiştirilmesi durumunda hareket etmek daha iyi bir yaklaşım olacaktır , GTK için bir örnek bu SO cevabında bulunabilir .

daha fazla okuma


3
Kullanılan CPU süresini gerçekten etkilemeden uyku aralığını kısaltabilirsiniz. Mac'imde bulundu: 0,01 s:% 69, 0,02 s:% 43, 0,05 s:% 25, ​​0,1 s:% 14, 0,2 s:% 7. 0,5 s: 3%
Floris

6
Yoklama hala berbat bir durum çünkü CPU önbelleklerini ve benzeri şeyleri kirleten bu süreci uyandırıyor. Yorumlarda tartışıldığı gibi bir pano değişikliğinin bildirilmesini beklemek daha iyi.
Peter Cordes

@ tatlı: Cevabı bilseydim yapardım. Ben sadece cevabınızda her 0.2 saniyede bir uyanmanın hala iyi bir tasarım olarak kabul edilmediğini ve oy kullanmayan bir yaklaşım aramanın çok daha iyi olacağını belirtmenizi öneririm . Ancak yalnızca bir bilgisayarda çalışacak olan bire bir kesmek için korkunç olmadığından ve muhtemelen yeterince iyi olduğundan emin olun.
Peter Cordes

26

Sonunda döngü olmadan çalışmasını sağladım. Bu kod:

Birkaç modül kurmak zorunda kaldım: sudo apt install python3-gi python3-gi-cairo gir1.2-gtk-3.0

#!/usr/bin/env python3
import gi, sys
gi.require_version('Gtk', '3.0')
from gi.repository import Gtk, Gdk

last_clipboard = ""

def callBack(*args):
  global last_clipboard
  new_clipboard = clip.wait_for_text()
  if new_clipboard != last_clipboard:
    last_clipboard = new_clipboard
    print("new Clipboard")
    print(new_clipboard)

clip = Gtk.Clipboard.get(Gdk.SELECTION_CLIPBOARD)
clip.connect('owner-change',callBack)
Gtk.main()

Size uygun çözümü seçmek için çekinmeyin.


Oooh… Neden clip.wait_for_text()iki kere talep ediyorsunuz ?
wizzwizz4

@ wizzwizz4 haklısın ben düzenlediğim ... tanklar
dmx

Herkes kopya iki kez yapmaz @ wizzwizz4 sadece emin olmak için?
Michael Frank

16

Bu şeyi bir while True:döngüde çalıştırıyorsunuz ! Bu, CPU’nun sürekli döngüde çalıştığını gösterir. Sadece küçük bir duraklama ekleyin ve CPU kullanımının yavaşça düşeceğini görmelisiniz:

#!/usr/bin/env python

import Tkinter
import time

last_clipboard = ""

def get_clipboard():
  global last_clipboard
  root = Tkinter.Tk()
  root.withdraw() # Hide the main window (optional)
  text_in_clipboard = root.clipboard_get()
  if text_in_clipboard != last_clipboard:
    last_clipboard = text_in_clipboard
    print last_clipboard

while True:
  get_clipboard()
  time.sleep(1)

3

Bu proje ilgimi çekti, bu yüzden o ortamda daha rahat olanlar için bir bash betiği yazdı:

#!/bin/bash

xclip -o -sel clip > /tmp/LastClip

while true ; do 

    xclip -o -sel clip > /tmp/NewClip
    diff -q /tmp/LastClip /tmp/NewClip > /tmp/DiffClip
    if [[ -s /tmp/DiffClip ]] ; then
        cat /tmp/NewClip    # For testing dump to screen instead of printing
        cp -a /tmp/NewClip /tmp/LastClip
    fi
    sleep 1.0

done

Xorg'un xclippaketini gerektiriyor :

sudo apt install xclip

catKomutu kullanarak pano içeriğini ekrana atıyor. Eğer basılı kopyasını istiyorsanız bunun yerine yerine catsahip lpve yazıcı adını, yönünü ve muhtemelen "uyum sayfasına" seçeneğini belirtin.

Ekranda biraz gecikme olduğunu göreceksiniz çünkü sleep 1.0hangisinin bir yazıcıyla farkedilmeyeceğini ve insanların metni vurgulayıp Ctrl+ tuşlarını kullanabildiğinden daha hızlı olacağını seçiyorum C.

Aynı vurgulu metni aynı panoya kopyalarsanız, bir fark tetiklemez. Bir veya daha fazla harf bir yanıtı tetikleyecektir.

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.