Programing

Python의 백그라운드 함수

crosscheck 2020. 10. 30. 07:45
반응형

Python의 백그라운드 함수


가끔 사용자에게 이미지를 표시하는 Python 스크립트가 있습니다. 이미지는 때때로 상당히 클 수 있으며 자주 재사용됩니다. 그것들을 표시하는 것은 중요하지 않지만 관련된 메시지를 표시하는 것은 중요합니다. 필요한 이미지를 다운로드하여 로컬에 저장하는 기능이 있습니다. 지금은 사용자에게 메시지를 표시하는 코드와 함께 인라인으로 실행되지만 로컬 이미지가 아닌 경우 10 초 이상 걸릴 수 있습니다. 필요할 때이 함수를 호출 할 수 있지만 코드가 계속 실행되는 동안 백그라운드에서 실행할 수있는 방법이 있습니까? 올바른 이미지를 사용할 수있을 때까지 기본 이미지를 사용합니다.


다음과 같이하십시오.

def function_that_downloads(my_args):
    # do some long download here

그런 다음 인라인으로 다음과 같이하십시오.

import threading
def my_inline_function(some_args):
    # do some stuff
    download_thread = threading.Thread(target=function_that_downloads, args=some_args)
    download_thread.start()
    # continue doing stuff

다음을 호출하여 다른 작업을 진행하기 전에 스레드가 완료되었는지 확인할 수 있습니다. download_thread.isAlive()


일반적으로이를 수행하는 방법은 스레드 풀을 사용하고 다운로드를 대기열에 추가하는 것입니다. 그러면 작업이 처리를 완료했다는 신호 (일명 이벤트)가 발생합니다. 파이썬이 제공 하는 스레딩 모듈 의 범위 내에서이를 수행 할 수 있습니다 .

이 작업을 수행하기 위해 이벤트 객체Queue 모듈을 사용 합니다.

그러나 간단한 threading.Thread구현을 사용하여 수행 할 수있는 작업에 대한 빠르고 더러운 데모는 아래에서 볼 수 있습니다.

import os
import threading
import time
import urllib2


class ImageDownloader(threading.Thread):

    def __init__(self, function_that_downloads):
        threading.Thread.__init__(self)
        self.runnable = function_that_downloads
        self.daemon = True

    def run(self):
        self.runnable()


def downloads():
    with open('somefile.html', 'w+') as f:
        try:
            f.write(urllib2.urlopen('http://google.com').read())
        except urllib2.HTTPError:
            f.write('sorry no dice')


print 'hi there user'
print 'how are you today?'
thread = ImageDownloader(downloads)
thread.start()
while not os.path.exists('somefile.html'):
    print 'i am executing but the thread has started to download'
    time.sleep(1)

print 'look ma, thread is not alive: ', thread.is_alive()

위에서하는 것처럼 설문 조사를하지 않는 것이 이치에 맞을 것입니다. 이 경우 코드를 다음과 같이 변경합니다.

import os
import threading
import time
import urllib2


class ImageDownloader(threading.Thread):

    def __init__(self, function_that_downloads):
        threading.Thread.__init__(self)
        self.runnable = function_that_downloads

    def run(self):
        self.runnable()


def downloads():
    with open('somefile.html', 'w+') as f:
        try:
            f.write(urllib2.urlopen('http://google.com').read())
        except urllib2.HTTPError:
            f.write('sorry no dice')


print 'hi there user'
print 'how are you today?'
thread = ImageDownloader(downloads)
thread.start()
# show message
thread.join()
# display image

여기에는 데몬 플래그가 설정되어 있지 않습니다.


나는 이런 종류의 일에 gevent 를 사용하는 것을 선호합니다 .

import gevent
from gevent import monkey; monkey.patch_all()

greenlet = gevent.spawn( function_to_download_image )
display_message()
# ... perhaps interaction with the user here

# this will wait for the operation to complete (optional)
greenlet.join()
# alternatively if the image display is no longer important, this will abort it:
#greenlet.kill()

Everything runs in one thread, but whenever a kernel operation blocks, gevent switches contexts when there are other "greenlets" running. Worries about locking, etc are much reduced, as there is only one thing running at a time, yet the image will continue to download whenever a blocking operation executes in the "main" context.

Depending on how much, and what kind of thing you want to do in the background, this can be either better or worse than threading-based solutions; certainly, it is much more scaleable (ie you can do many more things in the background), but that might not be of concern in the current situation.

참고URL : https://stackoverflow.com/questions/7168508/background-function-in-python

반응형