我正在尝试使用许多QThreads中的xmlrpc客户端。为了确保只有一个线程正在使用xmlrpc客户端,我使用QMutex创建了锁。我的代码:
import sys
import xmlrpclib
import threading
import time
from SimpleXMLRPCServer import SimpleXMLRPCServer
from PyQt4 import QtCore, QtGui
class MM(object):
def __init__(self):
self.lock = QtCore.QMutex()
self.xmlrpc_client = xmlrpclib.ServerProxy('http://localhost:9092')
def __getattr__(self, name):
self.lock.lock()
sys.stderr.write('locked, for %s\n' % name)
print threading.current_thread()
result = self.xmlrpc_client.__getattr__(name)
sys.stderr.write('unlocked by %s\n' % name)
self.lock.unlock()
return result
class Server(QtCore.QThread):
def __init__(self):
QtCore.QThread.__init__(self)
self.server = None
def run(self):
self.server = SimpleXMLRPCServer(("localhost", 9092), logRequests = False)
def one():
return 1
self.server.register_function(one, 'one')
self.server.serve_forever()
print "SERVER DONE"
class Ask(QtCore.QThread):
def __init__(self, mmInst):
QtCore.QThread.__init__(self)
self.mm = mmInst
self._stopping = False
def run(self):
while not self._stopping:
time.sleep(0.5)
print self.mm.one()
def stop(self):
self._stopping = True
self.wait()
def start_gui():
app = QtGui.QApplication(sys.argv)
server = Server()
server.start()
time.sleep(1)
mm = MM()
print mm.one()
a1 = Ask(mm)
a1.start()
a2 = Ask(mm)
a2.start()
try:
app.exec_()
except KeyboardInterrupt:
server.server.shutdown()
if __name__ == "__main__":
start_gui()
但它不起作用,我不知道为什么。输出结果如下:
locked, for one
<_MainThread(MainThread, started 1648)>
unlocked by one
1
locked, for one
<_DummyThread(Dummy-1, started daemon 356)>
unlocked by one
locked, for one
<_DummyThread(Dummy-2, started daemon 1480)>
unlocked by one
Traceback (most recent call last):
File "H:\poker\repos\TestSuite\test.py", line 46, in run
print self.mm.one()
File "C:\Python27\lib\xmlrpclib.py", line 1224, in __call__
return self.__send(self.__name, args)
File "C:\Python27\lib\xmlrpclib.py", line 1575, in __request
verbose=self.__verbose
File "C:\Python27\lib\xmlrpclib.py", line 1264, in request
return self.single_request(host, handler, request_body, verbose)
File "C:\Python27\lib\xmlrpclib.py", line 1289, in single_request
self.send_request(h, handler, request_body)
File "C:\Python27\lib\xmlrpclib.py", line 1391, in send_request
connection.putrequest("POST", handler, skip_accept_encoding=True)
File "C:\Python27\lib\httplib.py", line 853, in putrequest
raise CannotSendRequest()
httplib.CannotSendRequest
Traceback (most recent call last):
File "H:\poker\repos\TestSuite\test.py", line 46, in run
print self.mm.one()
File "C:\Python27\lib\xmlrpclib.py", line 1224, in __call__
return self.__send(self.__name, args)
File "C:\Python27\lib\xmlrpclib.py", line 1575, in __request
verbose=self.__verbose
File "C:\Python27\lib\xmlrpclib.py", line 1264, in request
return self.single_request(host, handler, request_body, verbose)
File "C:\Python27\lib\xmlrpclib.py", line 1294, in single_request
response = h.getresponse(buffering=True)
File "C:\Python27\lib\httplib.py", line 1015, in getresponse
raise ResponseNotReady()
httplib.ResponseNotReady
当只使用一个Thread时可以正常工作:
$ diff -u test.py.back test.py
--- test.py.back 2012-03-14 01:34:37.666425000 +0100
+++ test.py 2012-03-14 01:33:01.423265000 +0100
@@ -63,8 +63,8 @@
a1 = Ask(mm)
a1.start()
- a2 = Ask(mm)
- a2.start()
+ #a2 = Ask(mm)
+ #a2.start()
try:
app.exec_()
$ python test.py
locked, for one
<_MainThread(MainThread, started -1219930432)>
unlocked by one
1
locked, for one
<_DummyThread(Dummy-1, started daemon -1287918736)>
unlocked by one
1
locked, for one
<_DummyThread(Dummy-1, started daemon -1287918736)>
unlocked by one
1
locked, for one
<_DummyThread(Dummy-1, started daemon -1287918736)>
unlocked by one
1
当使用两个不同的MM实例时也可以正常工作:
$ diff -u test.py.back test.py
--- test.py.back 2012-03-14 01:34:37.666425000 +0100
+++ test.py 2012-03-14 01:38:47.352862000 +0100
@@ -57,13 +57,13 @@
time.sleep(1)
- mm = MM()
- print mm.one()
+ #mm = MM()
+ #print mm.one()
- a1 = Ask(mm)
+ a1 = Ask(MM())
a1.start()
- a2 = Ask(mm)
+ a2 = Ask(MM())
a2.start()
try:
adam@sabayon /media/Nowy/poker/repos/TestSuite $ python test.py
locked, for one
locked, for one
<_DummyThread(Dummy-1, started daemon -1288275088)><_DummyThread(Dummy-2, started daemon -1298138256)>
unlocked by one
unlocked by one
11
locked, for one
<_DummyThread(Dummy-2, started daemon -1298138256)>
unlocked by one
locked, for one
<_DummyThread(Dummy-1, started daemon -1288275088)>
unlocked by one
1
1
locked, for one
<_DummyThread(Dummy-1, started daemon -1288275088)>
unlocked by one
locked, for one
1<_DummyThread(Dummy-2, started daemon -1298138256)>
unlocked by one
1
答案 0 :(得分:2)
我在代码中看到了一些问题,但主要是我马上得到的问题是你在服务器准备好之前启动了客户端。当我首先实例化服务器,然后客户端,我停止了连接错误。
我还删除了你的旋转while循环,而只是启动了pyqt事件循环。你也没有真正将你的MM实例传递给你的Ask类(并不是因为你使用相同的实例而对这个例子很重要)。
无论如何,这是我的版本似乎起作用:
import sys
import xmlrpclib
import threading
import time
from SimpleXMLRPCServer import SimpleXMLRPCServer
from PyQt4 import QtCore, QtGui
class MM(object):
def __init__(self):
self.lock = QtCore.QMutex()
self.xmlrpc_client = xmlrpclib.ServerProxy('http://localhost:9092')
def __getattr__(self, name):
self.lock.lock()
sys.stderr.write('locked, for %s\n' % name)
print threading.current_thread()
result = self.xmlrpc_client.__getattr__(name)
sys.stderr.write('unlocked by %s\n' % name)
self.lock.unlock()
return result
class Server(QtCore.QThread):
def __init__(self):
QtCore.QThread.__init__(self)
self.server = None
def run(self):
self.server = SimpleXMLRPCServer(("localhost", 9092), logRequests = False)
def one():
return 1
self.server.register_function(one, 'one')
self.server.serve_forever()
print "SERVER DONE"
class Ask(QtCore.QThread):
def __init__(self, mmInst):
QtCore.QThread.__init__(self)
self.mm = mmInst
self._stopping = False
def run(self):
while not self._stopping:
time.sleep(0.5)
print self.mm.one()
def stop(self):
self._stopping = True
self.wait()
def start_gui():
app = QtGui.QApplication(sys.argv)
server = Server()
server.start()
time.sleep(.25)
mm = MM()
print mm.one()
a1 = Ask(mm)
a1.start()
a2 = Ask(mm)
a2.start()
try:
app.exec_()
except KeyboardInterrupt:
server.server.shutdown()
if __name__ == "__main__":
start_gui()
在进一步研究之后,我意识到它是python 2.7和xmlrpc中的一个错误,它改变了它创建连接的方式。 http://bugs.python.org/issue6907
奇怪的是,在OSX上的python 2.6 / 2.7或linux下的python 2.6上,这段代码不会崩溃。但是在Linux下使用python 2.7会让我崩溃。
当我将锁定机制移到MM实例之外时,似乎开始在linux下使用2.7:
class MM(object):
def __init__(self):
self.xmlrpc_client = xmlrpclib.ServerProxy('http://localhost:9093')
def __getattr__(self, name):
return self.xmlrpc_client.__getattr__(name)
class Ask(QtCore.QThread):
def __init__(self, mmInst, lock):
QtCore.QThread.__init__(self)
self.mm = mmInst
self.lock = lock
def run(self):
while not self._stopping:
time.sleep(0.5)
self.lock.lock()
print self.mm.one()
self.lock.unlock()
def start_gui():
app = QtGui.QApplication(sys.argv)
...
lock = QtCore.QMutex()
a1 = Ask(mm, lock)
a1.start()
a2 = Ask(mm, lock)
a2.start()