首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >wxPython和Autobahn websockets

wxPython和Autobahn websockets
EN

Stack Overflow用户
提问于 2014-06-30 18:09:42
回答 1查看 712关注 0票数 1

我试图为我的测试项目创建GUI应用程序,基于Python/Twisted/Autobahn.ws。Im如下文所示:wxPython与Twisted并尝试将我的应用程序连接到服务器。但一开始我会发现一个错误:

代码语言:javascript
复制
Unhandled Error
Traceback (most recent call last):
  File "/usr/local/lib/python2.7/dist-packages/twisted/python/log.py", line 88, in callWithLogger
    return callWithContext({"system": lp}, func, *args, **kw)
  File "/usr/local/lib/python2.7/dist-packages/twisted/python/log.py", line 73, in callWithContext
    return context.call({ILogContext: newCtx}, func, *args, **kw)
  File "/usr/local/lib/python2.7/dist-packages/twisted/python/context.py", line 118, in callWithContext
    return self.currentContext().callWithContext(ctx, func, *args, **kw)
  File "/usr/local/lib/python2.7/dist-packages/twisted/python/context.py", line 81, in callWithContext
    return func(*args,**kw)
--- <exception caught here> ---
  File "/usr/local/lib/python2.7/dist-packages/twisted/internet/_threadedselect.py", line 283, in _doReadOrWrite
    why = getattr(selectable, method)()
  File "/usr/local/lib/python2.7/dist-packages/twisted/internet/tcp.py", line 593, in doConnect
    self._connectDone()
  File "/usr/local/lib/python2.7/dist-packages/twisted/internet/tcp.py", line 607, in _connectDone
    self.protocol = self.connector.buildProtocol(self.getPeer())
  File "/usr/local/lib/python2.7/dist-packages/twisted/internet/base.py", line 1071, in buildProtocol
    return self.factory.buildProtocol(addr)
  File "/usr/local/lib/python2.7/dist-packages/twisted/protocols/policies.py", line 171, in buildProtocol
    return self.protocol(self, self.wrappedFactory.buildProtocol(addr))
  File "/usr/local/lib/python2.7/dist-packages/twisted/internet/protocol.py", line 123, in buildProtocol
    p = self.protocol()
exceptions.AttributeError: GUIClientProtocol instance has no __call__ method

我怎样才能解决这个问题?需要在我的类中定义调用方法,或者我有更好的解决方案?

代码: 1) client_gui:

代码语言:javascript
复制
import wx
from twisted.internet import wxreactor
wxreactor.install()

from twisted.internet import reactor, ssl
from autobahn.twisted.websocket import WebSocketClientFactory, WebSocketClientProtocol, connectWS

from gui.filemanager import CloudStorage

class GUIClientProtocol(WebSocketClientProtocol):

    def __init__(self, gui):
        self.gui = gui

if __name__ == '__main__':
    app = wx.App(False)
    frame = CloudStorage(None, -1, 'CloudStorage')
    frame.Show()

    host_url = "wss://%s:%s" % ("localhost", 9000)
    # create a WS server factory with our protocol
    factory = WebSocketClientFactory(host_url, debug = False)
    factory.protocol = GUIClientProtocol(frame)
    # SSL client context: using default
    if factory.isSecure:
        contextFactory = ssl.ClientContextFactory()
    else:
        contextFactory = None

    reactor.registerWxApp(app)
    connectWS(factory, contextFactory)
    reactor.run()

2) server.py

代码语言:javascript
复制
import sys
import datetime
import pickle
from json import dumps, loads
from hashlib import sha256
from time import gmtime, strftime
from subprocess import Popen, PIPE, STDOUT

import sqlalchemy
import sqlalchemy.exc
from sqlalchemy import and_, func, asc
from sqlalchemy.orm import sessionmaker
from twisted.internet import reactor, ssl
from twisted.internet.task import deferLater
from twisted.python import log, logfile
from twisted.web.server import Site
from twisted.web.wsgi import WSGIResource
from autobahn.twisted.websocket import WebSocketServerFactory, WebSocketServerProtocol, listenWS

from balancer.balancer import Balancer
from db.tables import File as FileTable
from db.tables import Users, FileServer, FileSpace, Catalog
from flask_app import app
from utils import commands


log_file = logfile.LogFile("service.log", ".")
log.startLogging(log_file)
engine = sqlalchemy.create_engine('postgresql://user:password@localhost/csan', pool_size=20, max_overflow=0)


def checkServerStatus(ip, port):
    p = Popen(["python", "statuschecker.py", str(ip), str(port)], stdout=PIPE, stdin=PIPE, stderr=STDOUT)
    result = p.communicate()[0].replace('\n', '')
    return result.split('|')


class DFSServerProtocol(WebSocketServerProtocol):

    ... # ~450 lines of code 

if __name__ == '__main__':
    if len(sys.argv) > 1 and sys.argv[1] == 'debug':
        log.startLogging(sys.stdout)
        debug = True
        port = int(sys.argv[2])
    else:
        debug = False
        port = int(sys.argv[1])

    contextFactory = ssl.DefaultOpenSSLContextFactory('web/keys/server.key', 'web/keys/server.crt')

    server_addr = "wss://localhost:%d" % (port)
    factory = WebSocketServerFactory(server_addr, debug = debug, debugCodePaths = debug)
    factory.protocol = DFSServerProtocol
    factory.setProtocolOptions(allowHixie76 = True)

    listenWS(factory, contextFactory)

    # Flask with SSL under Twisted
    resource = WSGIResource(reactor, reactor.getThreadPool(), app)
    site = Site(resource)
    reactor.listenSSL(8080, site, contextFactory)
    # reactor.listenTCP(8080, web)
    reactor.run()

更新1: client_gui.py看起来是这样的:

代码语言:javascript
复制
import wx
from twisted.internet import wxreactor
wxreactor.install()

from twisted.internet import reactor, ssl
from autobahn.twisted.websocket import WebSocketClientFactory, WebSocketClientProtocol, connectWS

from gui.filemanager import CloudStorage

class GUIClientProtocol(WebSocketClientProtocol):

    def __init__(self):
        WebSocketClientProtocol.__init__(self)
        self.gui = None

    def connectionMade(self):
        self.gui = self.factory._frame
        self.gui.Show()

if __name__ == '__main__':
    app = wx.App(False)
    frame = CloudStorage(None, -1, 'CloudStorage')

    # create a WS server factory with our protocol
    host_url = "wss://%s:%s" % ("localhost", 9000)
    factory = WebSocketClientFactory(host_url)
    factory.protocol = GUIClientProtocol
    factory._frame = frame

    # SSL client context: using default
    if factory.isSecure:
        contextFactory = ssl.ClientContextFactory()
    else:
        contextFactory = None

    reactor.registerWxApp(app)
    connectWS(factory, contextFactory)
    reactor.run()

更新2:

我的CloudStorage类代码:

代码语言:javascript
复制
import wx
import os
import time

ID_BUTTON=100
ID_EXIT=200
ID_SPLITTER=300

class MyListCtrl(wx.ListCtrl):
    def __init__(self, parent, id):
        wx.ListCtrl.__init__(self, parent, id, style=wx.LC_REPORT)

        files = os.listdir('.')
        images = ['images/empty.png', 'images/folder.png', 'images/source_py.png',
        'images/image.png', 'images/pdf.png', 'images/up16.png']

        self.InsertColumn(0, 'Name')
        self.InsertColumn(1, 'Ext')
        self.InsertColumn(2, 'Size', wx.LIST_FORMAT_RIGHT)
        self.InsertColumn(3, 'Modified')

        self.SetColumnWidth(0, 220)
        self.SetColumnWidth(1, 70)
        self.SetColumnWidth(2, 100)
        self.SetColumnWidth(3, 420)

        self.il = wx.ImageList(16, 16)
        for i in images:
            self.il.Add(wx.Bitmap(i))
        self.SetImageList(self.il, wx.IMAGE_LIST_SMALL)

        j = 1
        self.InsertStringItem(0, '..')
        self.SetItemImage(0, 5)

        for i in files:
            (name, ext) = os.path.splitext(i)
            ex = ext[1:]
            size = os.path.getsize(i)
            sec = os.path.getmtime(i)
            self.InsertStringItem(j, name)
            self.SetStringItem(j, 1, ex)
            self.SetStringItem(j, 2, str(size) + ' B')
            self.SetStringItem(j, 3, time.strftime('%Y-%m-%d %H:%M',
        time.localtime(sec)))

            # if os.path.isdir(i):
            #     self.SetItemImage(j, 1)
            # elif ex == 'py':
            #     self.SetItemImage(j, 2)
            # elif ex == 'jpg':
            #     self.SetItemImage(j, 3)
            # elif ex == 'pdf':
            #     self.SetItemImage(j, 4)
            # else:
            #     self.SetItemImage(j, 0)

            if (j % 2) == 0:
                self.SetItemBackgroundColour(j, '#e6f1f5')
            j = j + 1

class CloudStorage(wx.Frame):
    def __init__(self, parent, id, title):
        wx.Frame.__init__(self, parent, -1, title)

        self.splitter = wx.SplitterWindow(self, ID_SPLITTER, style=wx.SP_BORDER)
        self.splitter.SetMinimumPaneSize(50)

        p1 = MyListCtrl(self.splitter, -1)
        p2 = MyListCtrl(self.splitter, -1)
        self.splitter.SplitVertically(p1, p2)

        self.Bind(wx.EVT_SIZE, self.OnSize)
        self.Bind(wx.EVT_SPLITTER_DCLICK, self.OnDoubleClick, id=ID_SPLITTER)

        filemenu= wx.Menu()
        filemenu.Append(ID_EXIT,"E&xit"," Terminate the program")
        editmenu = wx.Menu()
        netmenu = wx.Menu()
        showmenu = wx.Menu()
        configmenu = wx.Menu()
        helpmenu = wx.Menu()

        menuBar = wx.MenuBar()
        menuBar.Append(filemenu,"&File")
        menuBar.Append(editmenu, "&Edit")
        menuBar.Append(netmenu, "&Net")
        menuBar.Append(showmenu, "&Show")
        menuBar.Append(configmenu, "&Config")
        menuBar.Append(helpmenu, "&Help")
        self.SetMenuBar(menuBar)
        self.Bind(wx.EVT_MENU, self.OnExit, id=ID_EXIT)

        tb = self.CreateToolBar( wx.TB_HORIZONTAL | wx.NO_BORDER |
        wx.TB_FLAT | wx.TB_TEXT)
        # tb.AddSimpleTool(10, wx.Bitmap('images/previous.png'), 'Previous')
        # tb.AddSimpleTool(20, wx.Bitmap('images/up.png'), 'Up one directory')
        # tb.AddSimpleTool(30, wx.Bitmap('images/home.png'), 'Home')
        # tb.AddSimpleTool(40, wx.Bitmap('images/refresh.png'), 'Refresh')
        # tb.AddSeparator()
        # tb.AddSimpleTool(50, wx.Bitmap('images/write.png'), 'Editor')
        # tb.AddSimpleTool(60, wx.Bitmap('images/terminal.png'), 'Terminal')
        # tb.AddSeparator()
        # tb.AddSimpleTool(70, wx.Bitmap('images/help.png'), 'Help')
        tb.Realize()

        self.sizer2 = wx.BoxSizer(wx.HORIZONTAL)

        button1 = wx.Button(self, ID_BUTTON + 1, "F3 View")
        button2 = wx.Button(self, ID_BUTTON + 2, "F4 Edit")
        button3 = wx.Button(self, ID_BUTTON + 3, "F5 Copy")
        button4 = wx.Button(self, ID_BUTTON + 4, "F6 Move")
        button5 = wx.Button(self, ID_BUTTON + 5, "F7 Mkdir")
        button6 = wx.Button(self, ID_BUTTON + 6, "F8 Delete")
        button7 = wx.Button(self, ID_BUTTON + 7, "F9 Rename")
        button8 = wx.Button(self, ID_EXIT, "F10 Quit")

        self.sizer2.Add(button1, 1, wx.EXPAND)
        self.sizer2.Add(button2, 1, wx.EXPAND)
        self.sizer2.Add(button3, 1, wx.EXPAND)
        self.sizer2.Add(button4, 1, wx.EXPAND)
        self.sizer2.Add(button5, 1, wx.EXPAND)
        self.sizer2.Add(button6, 1, wx.EXPAND)
        self.sizer2.Add(button7, 1, wx.EXPAND)
        self.sizer2.Add(button8, 1, wx.EXPAND)

        self.Bind(wx.EVT_BUTTON, self.OnExit, id=ID_EXIT)

        self.sizer = wx.BoxSizer(wx.VERTICAL)
        self.sizer.Add(self.splitter,1,wx.EXPAND)
        self.sizer.Add(self.sizer2,0,wx.EXPAND)
        self.SetSizer(self.sizer)

        size = wx.DisplaySize()
        self.SetSize(size)

        self.sb = self.CreateStatusBar()
        self.sb.SetStatusText(os.getcwd())
        self.Center()
        self.Show(True)

    def OnExit(self,e):
        self.Close(True)

    def OnSize(self, event):
        size = self.GetSize()
        self.splitter.SetSashPosition(size.x / 2)
        self.sb.SetStatusText(os.getcwd())
        event.Skip()

    def OnDoubleClick(self, event):
        size =  self.GetSize()
        self.splitter.SetSashPosition(size.x / 2)

if __name__ == '__main__':
    app = wx.App(0)
    CloudStorage(None, -1, 'CloudStorage')
    app.MainLoop()
EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2014-06-30 18:59:48

更新:我创建了一个完整的 示例 ,使用wxPython与Autobahn一起创建启用WebSocket的UI.

问题是这条线

代码语言:javascript
复制
factory.protocol = GUIClientProtocol(frame)

这将factory.protocol设置为GUIClientProtocol的一个实例。但它必须是全班的。

现在,您显然希望从frame内部访问GUIClientProtocol。(至少)有两个选择。

备选案文1:

代码语言:javascript
复制
factory.protocol = GUIClientProtocol
factory._frame = frame

然后从(正在运行的)协议实例以self.factory._frame的形式访问。

选项2:实现Factory.buildProtocol

票数 4
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/24496312

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档