web-dev-qa-db-ja.com

なぜこれがpythonスクリプトがバックグラウンドで実行され、CPUを100%消費しているのですか?)

クリップボードからテキストを読み取って出力する単純なpythonスクリプトをバックグラウンドで実行したいのですが、これが私のコードです。

#!/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()

これは期待どおりに機能していますが、CPUの消費量が多すぎます(100%CPU)。

それほど消費せずに正しく機能させるにはどうすればよいですか?

23
dmx

あなたのwhileループのtime.sleep()を忘れた、と SO のこの答えは、0.2秒間スリープすることは、ポーリング頻度とCPU負荷の間の適切な妥協点です。 :

_import time

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

0.2秒ごとにクリップボードをチェックするのは簡単なことのようです。 CPU負荷を減らしたい場合は、この値を増やすこともできます。クリップボードの内容を1秒ごとに変更するユーザーはほとんどいません。

一般に、ループでのポーリングは、それが適切な設計とは見なされない頻度で行われることに注意してください。より良いアプローチは、クリップボードの内容を変更するイベントに基づいて行動することです。GTKの例は にありますSO答え

参考文献

44
dessert

最後にループなしで動作するようにします。これはコードです:

いくつかのモジュールをインストールする必要がありました: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()

自分に合ったソリューションを自由に選択してください。

27
dmx

while True:ループで実行しています!つまり、CPUは常にループを実行しています。そこに小さな一時停止を追加するだけで、CPU使用率が急激に低下するはずです。

#!/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)
16
terdon

私はこのプロジェクトに興味をそそられたので、その環境でより快適な人のためにbashスクリプトを書きました。

#!/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のxclipパッケージが必要です:

Sudo apt install xclip

catコマンドを使用して画面にクリップボードの内容をダンプしています。ハードコピーが必要な場合は、代わりにcatlpに置き換え、プリンター名、方向、および場合によっては「ページに合わせる」オプションを指定します。

私はsleep 1.0を選択しているため、画面に少し遅れが見られます。これは、プリンタでは目立たず、テキストをハイライトして使用するよりも高速です。 Ctrl+C

まったく同じ強調表示されたテキストをクリップボードにコピーしても、違いは発生しません。 1文字多かれ少なかれ応答をトリガーします。

4