线程。线程一直打httplib2。Http.reques

2024-06-26 14:05:14 发布

您现在位置:Python中文网/ 问答频道 /正文

脚本的前几行解释了结构和机制。在

我面临的问题是,执行工作在第53行卡住了。一旦下载程序对第一个请求采取行动,它就会正确地生成api,但是在到达http_object.request(audioscrobbler_api)时,它就会卡住。在

在另一个系统上对脚本进行了编码和测试,结果是正确的。在

我可以确认httplib2包没有被破坏,因为它在从其他脚本调用该库的方法(包括request)时正常工作。在

是什么导致脚本卡住了?在

脚本:

#
# Album artwork downloading module for Encore Music Player application.
# Loosely based on the producer-consumer model devised by E W Djikstra.
#
# The Downloader class (implemented as a daemon thread) acts as the consumer
# in the system where it reads requests from the buffer and tries to fetch the
# artwork from ws.audioscrobbler.com (LastFM's web service portal).
#
# Requester class, the producer, is a standard thread class that places the request
# in the buffer when started.
#
# DBusRequester class provides an interface to the script and is made available on
# the session bus of the DBus daemon under the name of 'com.encore.AlbumArtDownloader'
# which enables the core music player to request downloads.
#

import threading, urllib, httplib2, md5, libxml2, os, dbus, dbus.service, signal
from collections import deque
from gi.repository import GObject
from dbus.mainloop.glib import DBusGMainLoop

requests = deque()
mutex    = threading.Lock()
count    = threading.Semaphore(0)

DBusGMainLoop(set_as_default = True)

class Downloader(threading.Thread):

        def __init__(self):
                threading.Thread.__init__(self)

        def run(self):

                while True:
                        print "=> Downloader waiting for requests"
                        count.acquire()  # wait for new request if buffer is empty

                        mutex.acquire()  # enter critical section
                        request = requests.popleft()
                        mutex.release()  # leave critical section

                        (p, q) = request

                        try:
                                print "=> Generating api for %s by %s" % (p,q) 
                                params             = urllib.urlencode({'method': 'album.getinfo', 'api_key': 'XXX', 'artist': p, 'album': q})
                                audioscrobbler_api = "http://ws.audioscrobbler.com/2.0/?%s" % params
                                print "=> Generated URL %s" % (audioscrobbler_api)

                                http_object   = httplib2.Http()
                                print "=> Requesting response"
                                resp, content = http_object.request(audioscrobbler_api)
                                print "=> Received response"

                                if not resp.status == 200:
                                        print "Unable to fetch artwork for %s by %s" % (q, p)
                                        continue                 # proceed to the next item in queue if request fails

                                doc  = libxml2.parseDoc(content)
                                ctxt = doc.xpathNewContext()
                                res  = ctxt.xpathEval("//image[@size='medium']") # grab the element containing the link to a medium sized artwork

                                if len(res) < 1:
                                        continue                 # proceed to the next item in queue if the required image node is not found

                                image_uri = res[0].content           # extract uri from node

                                wget_status = os.system("wget %s -q --tries 3 -O temp" % (image_uri))

                                if not wget_status == 0:
                                        continue                 # proceed to the next item in queue if download fails

                                artwork_name = "%s.png" % (md5.md5("%s + %s" % (p, q)).hexdigest())

                                os.system("convert temp -resize 64x64 %s" % artwork_name)
                        except:
                                pass                         # handle http request error 

class Requester(threading.Thread):

        def __init__(self, request):
                self.request = request
                threading.Thread.__init__(self)

        def run(self):
                mutex.acquire() # enter critical section
                if not self.request in requests:
                        requests.append(self.request)
                        count.release() # signal downloader

                        mutex.release() # leave critical section

class DBusRequester(dbus.service.Object):

        def __init__(self):
                bus_name = dbus.service.BusName('com.encore.AlbumArtDownloader', bus=dbus.SessionBus())
                dbus.service.Object.__init__(self, bus_name, '/com/encore/AlbumArtDownloader')

        @dbus.service.method('com.encore.AlbumArtDownloader')
        def queue_request(self, artist_name, album_name):

                request   = (artist_name, album_name)
                requester = Requester(request)
                requester.start()

def sigint_handler(signum, frame):
        """Exit gracefully on receiving SIGINT."""

        loop.quit()

signal.signal(signal.SIGINT, sigint_handler)

downloader_daemon = Downloader()
downloader_daemon.daemon = True
downloader_daemon.start()

requester_service = DBusRequester()

loop = GObject.MainLoop()
loop.run()

在进行Ctrl-C操作时

^{pr2}$

谢谢!!在


Tags: thetonameselfapiifrequestdef
2条回答

这个问题是由Python的全局解释器锁(GIL)引起的。在

GObject.threads_init()

解决问题。在

当您的脚本在第53行卡住时,您可以使用Ctrl+C中断执行并向我们展示python提供的回溯吗?在

相关问题 更多 >