3

我是一名行为科学家,通常通过让参与者在计算机上完成一些任务并记录他们的反应来收集数据(我使用 pyglet 包装器PsychoPy编写程序)。即程序在本地运行,数据在本地存储。

现在我想知道是否有一种方法可以使用 Python 向用户显示带有 html-forms 的(本地)网站并收集(本地)输入。这个想法的原因是,目前每当我想显示复选框、单选按钮或输入字段时,我都会使用 wxPython。这工作得很好,但是在 wxPython 中编程和布局有点麻烦,我更喜欢带有表单的 html。

一个要求是它需要朗姆酒,没有任何边框,地址字段,菜单栏,......原因是我需要它以全屏模式(我目前打开一个非全屏pygflet窗口的大小屏幕以隐藏桌面),以便参与者只能在表格上工作。

因此,我正在寻找一种方法来(a)在没有菜单栏或其他任何内容的 pyglet 窗口上方显示 html 网站,包括 html 表单,(b)在单击“确定”按钮时收集输入(即,表单已发送),( c) 控制查看本网站之前和之后显示的内容,以及 (d) 这一切都应该在本地发生!

我的想法是当参与者点击以下示例图片中的“发送”按钮并显示下一页时收集数据。

示例表格

更新:我使用 Windows(XP 或 7)。

4

5 回答 5

5

这是一个使用 Qt Webkit 渲染 HTML 的解决方案。默认导航请求处理程序由检查提交的表单请求的函数包装。该表单使用“get”方法,因此数据包含在请求的 url 中,并且可以通过这种方式检索。原始请求被拒绝,您可以根据需要更改显示网页的内容。

from PyQt4 import QtGui, QtWebKit

app = QtGui.QApplication([])
view = QtWebKit.QWebView()

# intercept form submits
class MyWebPage(QtWebKit.QWebPage):
    def acceptNavigationRequest(self, frame, req, nav_type):
        if nav_type == QtWebKit.QWebPage.NavigationTypeFormSubmitted:
            text = "<br/>\n".join(["%s: %s" % pair for pair in req.url().queryItems()])
            view.setHtml(text)
            return False
        else:
            return super(MyWebPage, self).acceptNavigationRequest(frame, req, nav_type)
view.setPage(MyWebPage())

# setup the html form
html = """
<form action="" method="get">
Like it?
<input type="radio" name="like" value="yes"/> Yes
<input type="radio" name="like" value="no" /> No
<br/><input type="text" name="text" value="Hello" />
<input type="submit" name="submit" value="Send"/>
</form>
"""
view.setHtml(html)

# run the application
view.show()
app.exec_()
于 2012-04-19T22:08:33.460 回答
4

正如 AdamKG 所提到的,使用网络框架将是一个不错的选择。由于 Django 和类似的东西在这里可能有点过分,所以使用像“ flask ”或“ bottle ”这样的微型网络框架将是一个不错的选择。

链接通过分步说明演示如何通过待办事项应用程序制作简单的表单。它假设先前的知识为零。

您也只能在本地运行它。

于 2012-04-18T09:04:21.723 回答
3

您想要一个简单的解决方案,所以只需编写一个 http 服务器并运行您的简单页面。

使用python.BaseHTTPServer,编写一个15 行的Web 服务器:

import BaseHTTPServer

class WebRequestHandler(BaseHTTPServer.BaseHTTPRequestHandler):
    def do_GET(self):
        if self.path == '/foo':
            self.send_response(200)
            self.do_something()
        else: 
            self.send_error(404)

    def do_something(self):
        print 'hello world'

server = BaseHTTPServer.HTTPServer(('',80), WebRequestHandler)
server.serve_forever()

很简单,但我建议使用一些网络框架。他们也很容易。

例如,web.py。这是你想要的50 行代码

  1. 安装 web.py
  2. 创建一个包含 2 个文件的目录:

    ./
    |-- app.py
    `-- templates
        `-- index.html
    
  3. 索引.html

    $def with (form, ret)

    <html>
    <head>
                    <title> another site </title>
    </head>
    <body>
            <h1> hello, this is a web.py page </h1>
    
            <form action="" method="post">
                    $:form.render()
            </form>
    
            <h2>$:ret</h2>
    
    </body>
    </html>
    
  4. app.py 逻辑文件:

    import web
    
    ### Url mappings
    
    urls = (
         '/', 'Index', )
    
    ### Templates 
    render = web.template.render('templates')
    
    class Index:
        form = web.form.Form(
            web.form.Textbox('fav_name', web.form.notnull, description="Favorite Name:"),
            web.form.Textbox('cur_name', web.form.notnull, description="Current Name:"),
            web.form.Button('Send Away'),
        )
    
        def GET(self):
            """ Show page """
            form = self.form()
            return render.index(form, "")
    
        def POST(self):
            """ handle button clicked """
            form = self.form()
            if not form.validates():
                return render.index(form, "INPUT ERROR")
    
            # save data by ur method, or do some task
            #pyglet.save_data(form.d.fav_name, form.d.cur_name)
            #pyglet.draw(some_pic)
            #os.system(some_cmd)
    
            form = self.form()
            return render.index(form, "YOUR DATA SAVED")
    
    app = web.application(urls, globals())
    
    if __name__ == '__main__':
        app.run()
    
  5. 在您的 Windows 中运行此服务器:

    蟒蛇应用程序.py 9999

  6. 打开浏览器:http: //127.0.0.1 :9999/

顺便说一句,如果你的数据只是字符串,你可以通过 sqlite 将它们保存在 web.by 中。

于 2012-04-20T11:54:57.810 回答
1

这个想法的原因是,目前每当我想显示复选框、单选按钮或输入字段时,我都会使用 wxPython。这工作得很好,但是在 wxPython 中编程和布局有点麻烦,我更喜欢带有表单的 html。

您可以结合 HTML 的易用性,并仍然使用带有 Python 后端的Flex创建本机 Windows 应用程序。

如果您不喜欢 Flex,那就多一点 - 涉及 - 但仍然是原生 Windows 应用程序生成器是Camelot

编辑

而不是再次输入它 - 我建议 Adob​​e 上的django + flex + pyamf文章也用屏幕截图解释了这一切。您可以用 flask 或 bottle 替换 django,因为它们更轻量级,但是 PyAMF 库为 django 提供本机支持,这就是在示例中使用它的原因。

PyAMF 为 Python 提供Action Message Format(与 Flash 运行时交换对象的二进制协议)支持。

于 2012-04-19T07:10:30.110 回答
1

我的建议是:

  1. 使用一些 python 服务器,例如SimpleHTTPServer. 它是必需的,因为表单上的提交按钮将信息发送到服务器。在那里你应该以某种方式管理收到的信息;
  2. 将您的浏览器配置为使用其中一种 Kiosk 扩展,这甚至不允许使用 Alt+F4。一个例子是Firefox 的Open Kiosk扩展
  3. 或者,如果您通常与脚本有密切关系,您可以创建一个脚本,该脚本在执行时将同时运行 python 服务器并在浏览器中打开您的 html 文件。这将大大减轻您对小组中每个主题的设置工作。

编辑:我读过你需要浏览器窗口上的 pyglet。这可以包含在步骤 3 的脚本中,使用“始终在顶部”选项和 pyglet 的绝对定位(我可以说这在 Linux 上可能会更简单,可以从持久 LiveUSB 运行 - 只是一个想法!)

编辑(关于发布的评论):我认为最可靠的输出选项是磁盘(文件或数据库)而不是 RAM(运行 python 对象),然后你从文件中读取信息。然后,如果发生意外(系统挂起、电源故障),已经输入的数据会在那里。

我不知道如何做的唯一(也是最重要的)部分是在服务器端处理表单“提交”的内容。可能应该创建一些服务器端脚本文件(php,python)并将其保留在服务器根目录中,因此服务器将接收包含信息的 http 请求,并将信息发送到脚本,然后处理处理和文件/数据库存储活动。

这可能会引起您的兴趣:“当客户端需要将数据作为请求的一部分发送到服务器时,例如在上传文件或提交完整的表单时,使用 POST 请求方法。” (来自维基百科的“POST(HTTP)”条目)

在另一个链接中,关于使用SimpleHTTPServer自身处理 POST 请求的一些想法:http: //islascruz.org/html/index.php/blog/show/Python%3A-Simple-HTTP-Server-on-python..html

希望这可以帮助。

于 2012-04-14T15:10:07.337 回答