이 파이썬 스크립트가 백그라운드에서 100 % CPU를 소비하는 이유는 무엇입니까?


22

클립 보드에서 텍스트를 읽고 인쇄하는 백그라운드에서 간단한 파이썬 스크립트를 실행하고 싶습니다. 여기 내 코드가 있습니다.

#!/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)를 소비합니다.

그렇게 많이 소비하지 않고 올바르게 작동하게하려면 어떻게해야합니까?


26
사용중인 프레임 워크가 전혀 지원하지 않는 경우 이벤트 기반 코드를 사용하여 루프가 아닌 클립 보드의 변경 사항을 감지하십시오. 클립 보드가 변경 될 때까지 클립 보드를 계속 가져 오거나 변경되었음을 알려주는 시스템을 듣는 것에는 차이가 있습니다.
스테판

6
@dessert 파이썬에서 한 번도 해 본 적이 없지만 GTK의 해결책 인 것 같습니다 : stackoverflow.com/a/25961646/985296 (플랫폼 의존성은 언급하지 않았습니다).
스테판

@ jpmc26 & dessert 메타 토론처럼 보입니다. 부담없이 들려주세요. 확실히 범위 내에서 이를 정리할 수있는 좋은 아이디어 입니다.
마스트

1
@dessert JPMC가 이것이 주제인지 여부에 대해 논의하려는 경우 메타 스레드를 엽니 다. 이 주장에 대해서는 언급하지 마십시오. (댓글 정리가 완료되었으며 메타 토론이 진행되는 동안 1 주일 동안 주제가 잠겼지만 댓글 논쟁도 중단했습니다.)
Thomas Ward

답변:


44

당신은 잊었 time.sleep()당신의 while루프에 따라 SO에 대한이 답변 0.2 초 자고하는 것은 폴링 주파수와 CPU 부하 사이 좋은 타협이다 :

import time

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

0.2 초마다 클립 보드를 점검하는 것은 종종 쉽게 보인다. CPU로드를 줄이려면이 값을 늘릴 수도 있습니다. 몇 초 동안 클립 보드 내용을 변경하는 사용자는 거의 없습니다.

일반적으로 루프에서 자주 폴링하는 것은 좋은 디자인으로 간주되지 않습니다. 더 나은 접근 방법은 클립 보드 내용을 변경 하는 경우 조치를 취하는 것 입니다. 이 SO answer에서 GTK의 예를 찾을 수 있습니다 .

추가 자료


3
실제로 사용 된 CPU 시간에 영향을주지 않고 절전 간격을 짧게 만들 수 있습니다. Mac에서 발견 : 0.01 초 : 69 %, 0.02 초 : 43 %, 0.05 초 : 25 %, 0.1 초 : 14 %, 0.2 초 : 7 %. 0.5 초 : 3 %
플로리스

6
폴링은 CPU 캐시 등을 오염시키는이 프로세스를 계속 깨우기 때문에 여전히 짜증납니다. 의견에서 논의했듯이 클립 보드 변경 알림을 기다리는 것이 훨씬 좋습니다.
Peter Cordes

@dessert : 대답을 알고 있다면 그렇게 할 것입니다. 나는 단지 0.2 초마다 깨우는 것이 여전히 좋은 디자인으로 간주되지 않으며 비 폴링 접근법을 찾는 것이 훨씬 나을 것이라고 당신의 대답에 언급 할 것을 제안합니다 . 그러나 한 대의 컴퓨터에서만 실행되는 일회성 해킹의 경우 끔찍하지 않으며 아마도 충분할 것입니다.
Peter Cordes

26

마침내 루프없이 작동하게합니다. 이것은 코드입니다.

몇 개의 모듈을 설치해야했습니다. 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()

귀하에게 적합한 솔루션을 자유롭게 선택하십시오.


우… 왜 clip.wait_for_text()두 번 요청 합니까?
wizzwizz4

@ wizzwizz4 당신이 맞아요 편집했습니다 ... 탱크
dmx

@ wizzwizz4 모든 사람이 두 번만 복사하지는 않습니까?
마이클 프랭크

16

당신은 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)

3

나는이 프로젝트에 흥미가 있었기 때문에 그 환경에서 더 편안한 사람들을 위해 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.

정확히 동일한 강조 표시된 텍스트를 클립 보드에 복사해도 차이가 발생하지 않습니다. 하나 이상의 문자가 응답을 트리거합니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.