怎么样在 virtualenv 里面使用 PyQt

PyQt 现在还不支持从pip下载安装,习惯virtualenv开发的时候会比较麻烦,总不能为了一个 PyQt 就放弃了virtualenv吧。

有多种方案可以实现这个目标。我这里从源代码开始安装 PyQt,好像是不同的项目可以使用不同的版本。编译的时候我只编译了QtCore, QtGui, QtWidgets三个模块。

具体的步骤与命令看正文吧。

类型:Python,C++ & Qt4,创建时间:五月 5, 2017, 10:23 a.m. 点击查看完整内容。。。
为什么不要使用QThread

之前我在Python中使用线程的技巧一文中提到,尽量不要在 PyQt 里面使用QThread,但是当时没有给出示例程序。这里补上一个会引起Python崩溃的代码。其实主要原因是QThread被强制关闭的时候会引起Python崩溃。

代码请见正文。

类型:Python,C++ & Qt4,创建时间:一月 6, 2015, 5:08 p.m. 点击查看完整内容。。。
Python与C++联合编程的简介

作为Python程序员,应该能够正视Python的优点与缺点。众所周之,Python的运行速度是很慢的,特别是大数据量的运算时,Python会慢得让人难以忍受。对于这种情况,“专业”的解决方案是用上numpy或者opencl。不过有时候为了一点小功能用上这种重型的解决方案很不划算,或者有时候想要实现的操作在numpy里面没有,需要我们自己用C语言来编写。总之,我们使用Python与C++的混合编程能够加快程序热点的运算速度。

还有些情况,Python程序员们想要使用操作系统或者外部模块提供的函数。这些模块一般是为C/C++程序员提供的。这时候也是Python与C++联合编程的用武之地。

Python语言可以说是最好的胶水语言。仅就与C++联合编程这个问题来讲,依使用难度与功能来排列,Python社区提供了以下几种解决方案:

  1. 使用标准库ctypes直接调用C/C++编写的动态链接库。
  2. 如果你使用的是Jython或者IronPython的话,它们也提供了类似于ctypes之类的模块,能够直接访问Java或者.Net语言编写的模块。
  3. 使用Cython语言,一种类似于Python语言的一种新型语言编写预定功能的代码,然后将这些代码转换成为C语言编译成为Python语言可以直接调用的二进制模块。
  4. 使用boost.python。供熟练的C++程序员操作Python的数据类型,调用Python解释器。
  5. 使用SWIG或者SIP,通过编写一个接口文件,使用类似于C/C++语法——声明函数、类型的信息,然后使用特殊的工具为C/C++的代码生成Python的接口代码。
  6. 直接使用Python的API,可以称之为最终解决方案。
类型:Python,创建时间:三月 22, 2013, 8:47 p.m. 点击查看完整内容。。。
Coroutine在PyQt中的简单应用

在PyQt程序内操纵网络连接是一个非常常见的需求。目前,纯粹的单机程序已经非常的少见。解决这个问题,习惯于C++的Qt开发者第一个反应可能是QtNetwork,而习惯于Python的开发者第一个反应则是Python的标准库socket, urllib2或者第三方模块requests等。

本文提供了另外一种解决方案,基于coroutine的UI编程。与基于threading的同步编程方案相比,第三种方案能够免去同步的麻烦,非常适合天生线程不安全的UI编程。与signal/slot, 回调式的编程相比,第三方案的控制结构更清晰,资源管理更高效,非常适合复杂的逻辑UI操作。

本文还可作为eventlet-pyqt的编程指导。

类型:Python,创建时间:三月 12, 2013, 5:33 p.m. 点击查看完整内容。。。
Python 代码优化常见技巧(转载)

代码优化能够让程序运行更快,它是在不改变程序运行结果的情况下使得程序的运行效率更高,根据 80/20 原则,实现程序的重构、优化、扩展以及文档相关的事情通常需要消耗 80% 的工作量。优化通常包含两方面的内容:减小代码的体积,提高代码的运行效率。本文介绍:

  • 改进算法,选择合适的数据结构
  • 对循环优化
  • 充分利用 Lazy if-evaluation 的特性
  • 字符串优化
  • 其他优化技巧
  • 定位程序性能瓶颈
  • 使用PyPy或者Cython
类型:Python,创建时间:九月 17, 2012, 6:18 p.m. 点击查看完整内容。。。
py3k新特性——声明参数类型的函数

众所周知,Python是一种强类型动态语言。“动态”意味着Python从不声明变量的类型。可以认为Python里面,一切变量的类型都是自动推定的。

这种灵活又智能的设定让程序员们写代码时不用花时间去考虑定义变量的类型,又方便程序员设计出灵活的程序。写过Python代码的人朋友们一般会觉得写Python程序很爽。

不过,因为在定义函数的时候也没有参数的传递,合作者往往难以确定传入的参数类型。再者,即使IDE可以自动地推定变量的类型,也难以推断函数参数的类型,不好做自动补全。

幸运的是,现在,Python 3.0已经克服了这个缺点,可以声明参数类型了。请点击“阅读更多”查看本文。

类型:Python,创建时间:五月 29, 2012, 11:25 a.m. 点击查看完整内容。。。
如何设计插件式结构的程序,兼谈Python语言的动态性

为了扩充软件的功能,通常我们会把软件设计成插件式结构。Python这样的动态语言天生就支持插件式编程。与C++相比,Python已经定义好模块的接口,想要载入一个插件,一个__import__()就能很轻松地搞定。不需要特定的底层知识。而且与C++等静态语言相比,Python的插件式结构更显灵活。因为插件载入后,可以利用Python语言的动态性,充分地修改核心的逻辑。

本文不止用几个最简单的程序示范了如何设计插件式结构。还演示了插件的两种布署方法以及一些小技巧。详细内容请点击查看全文。

类型:Python,创建时间:三月 23, 2012, 5:46 p.m. 点击查看完整内容。。。
Python中使用线程的技巧

这篇长文介绍了Python如何创建一个新线程,以及几个注意事项:

  1. 创建线程的两种方法,以及它们的正确写法。
  2. 创建线程的第三种写法。
  3. 如何“强制地”结束一个线程。
  4. 不要在线程里面import新模块
  5. 不要使用PyQt的QThread类。
  6. 不要在非主线程里面使用QObject的对象。
类型:Python,C++ & Qt4,创建时间:三月 14, 2012, 8:59 p.m. 点击查看完整内容。。。
最全的Tkinter教程与参考手册

这本是我见过的最全的Tkinter教程与参考手册。主要介绍了Tkinter的Layout模型、控件的标准属性、事件。详细列出了每一种控件的属性的意义。里面还有很多的代码例子,实在是一本不可多得的好书。

点击下载

类型:Python,创建时间:三月 14, 2012, 11:16 a.m. 点击查看完整内容。。。
在PyQt里面如何做长操作时同时更新GUI

经常看到有人问在PyQt里面如何做长操作的时候更新GUI。我自己总结了几种方案,以及他们的适用场合:

  1. 使用processEvents(),适合每次处理时间短的情况,缺点是CPU占用可能很大。
  2. 用threading启动工作线程,再用QMetaObject.invokeMethod()向主线程传递跨线程的信息。
  3. QProgressDialog。有同步与异步两种方法。
  4. 把长的操作分为小的操作,适合每次处理都是异步的或者很复杂的情况。

第四种方案不常用,但是当你的处理过程本身是异步的时候就会用到。第一、第二方案都不错,优点是灵活。第三种方案也常见,优点是模态对话框阻止用户的其它操作,可以随时取消。缺点是一个对话框挡在那里,相当地影响用户体验。

类型:Python,C++ & Qt4,创建时间:一月 17, 2012, 3:53 p.m. 点击查看完整内容。。。
Django的MEDIA_ROOT和STATIC_ROOT

在水木的Python版问了一下,MEDIA_ROOT主要是用来放置上传的文件。Django的ORM有个特殊的字段叫做FileField是用来存储文件的。不过实际上并不会把文件内容存到数据库里面——因为大多数数据库保存文件时效率低,而是保存在文件系统里面。FileField只记录一个路径。FileField可以像个Python的file类型那样读写。

在开发的时候MEDIA_ROOT不应该存放任何文件。它应该指向一个空的目录。运行Django的开发服务器时,需要在urls.py里面加入一个MEDIA_URL的映射,才能正常显示上传的内容:

from django.conf import settings

if settings.DEBUG:
    urlpatterns += patterns(",
            url(r"^media/(?P<path>.*)$", \
                "django.views.static.serve", \
                {"document_root": settings.MEDIA_ROOT,}),
)

当工程被布署到Apache时也要记得给MEDIA_URL做个映射。

STATIC_ROOT是Django 1.3新增的特性。如同字面上的意思。保存在这个目录里面文件被当成静态文件处理。不过,千万不要把自己辛苦写的JavaScript、图片等静态文件放到里面去,接着看下去就知道了。与STATIC_ROOT搭配使用的还有STATIC_URLSTATICFILES_DIRS两个变量。STATIC_URL一般用默认的/static/,用于指定的静态目录的URL。STATICFILES_DIRS则指定一个工程里面哪个目录存放了与这个工程相关的静态文件,它是一个列表。假定在STATICFILES_DIRS有一个目录是"/dolphin/besteam/pages/static",其中有一个文件是common.js。那么,在浏览器里面输入http://localhost:8000/static/common.js就可以访问这个JavaScript文件了。

类型:Python,创建时间:一月 1, 2012, 7:14 p.m. 点击查看完整内容。。。
将Python程序打包成.zip文件并发布

在部署Python程序的时候。一般是把所有的源代码复制到目标机器上。我发现一个更好的办法是把源代码打包成.zip文件,然后直接运行这个.zip文件。比如:

python besteam.zip

它的秘密是在.zip文件中包含一个__main__.py,当python运行这个zip时,会自动找到它并运行。__main__.py的内容一般是调用主脚本。一行即可,比如:

import besteam
类型:Python,创建时间:一月 1, 2012, 7:02 p.m. 点击查看完整内容。。。
Python的类、对象,以及classmethod的意义

先看一下这两行代码:

>>> class Fish:pass
>>> f=Fish()

f就是Fish类的实例,它是一个对象(object),很明显吧。 Fish是类,它也是一个对象(object),如果你以前学的是C++或者Java,可能会难以理解。 不管怎么样,在Python内部,它们都用一个PyObject结构体表示,你可以修改对象的属性, 调用它们的方法。

类与实例两种对象有什么区别呢,下面的代码运行于python 3.1版本:

>>> Fish.isAnimal=True
>>> print(f.isAnimal)
True

我们定义Fish是一种动物,显然f更是一种动物了。

>>> f.name="老鱼"
>>> print(Fish.name)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
AttributeError: type object 'Fish' has no attribute 'name'

我们定义f这条鱼的名字是"老鱼"。这时候,Fish并不会自动拥有名字这个属性,总不能说 鱼都是叫“老鱼”吧。

类的实例可能比较好理解,但是类居然可以有属性,可能有些C++/Java程序员难以理解。

使用classmethod修饰的函数第一个参数是类对象。平时它没什么用,只有继承关系比较复 杂的时候才能派上用场。我以前学classmethod的时候写过一段代码:详情请点击查看正文。

类型:Python,创建时间:一月 1, 2012, 6:46 p.m. 点击查看完整内容。。。
打造自己习惯的Python命令行环境

使用过一段时间的Python之后,大多数朋友可能已经发现自己经常使用的是Python某一部分的功能。比如习惯拿Python来当计算器的朋友,最喜欢的是运行Python的命令行之后就打一个:

from __future__ import division
from math import *

每次运行之后都要输入这些命令不免麻烦,幸好Python开发者早就替我们考虑好这个问题了。可以通过设置"PYTHONSTARTUP"这个环境变量让Python命令行每次运行后都自动做这些事。

比如,我们可以编写一个名为startup.py的文件,它的内容是:

from __future__ import division
from math import *

假设将它保存到H:\Documents\myconfig\startup.py。然后设置环境变量PYTHONSTARTUP=H:\Documents\myconfig\startup.py。下次运行Python命令行之后,输入sqrt(2)试试。

类型:Python,创建时间:一月 1, 2012, 6:33 p.m. 点击查看完整内容。。。
PyQt里让文本编辑器自动滚动

前两天看txt小说的时候,手头找不到小说阅读器,就顺手写了一个。主要功能是让文字自动滚动。原理超简单,让QTextBrowser的滚动条每隔一段时间往下拉一点就可以了。好了,上代码:

vb=self.textBrowser.verticalScrollBar()
if vb.value()>=vb.maximum():
    return
vb.setValue(vb.value() + 2)

据我试验,QPlainTextEdit滚动条拉动时以行为单位,每次滚动只能下拉一行。用QTextEditQTextBrowser不会有这个问题。

类型:Python,C++ & Qt4,创建时间:一月 1, 2012, 5:54 p.m. 点击查看完整内容。。。
编写兼容Python2.6与Python3.0的程序

简而言之,在所有的py文件头加上:

# -*- coding:utf-8 -*-
from __future__ import print_function
from __future__ import unicode_literals
from __future__ import division
from __future__ import absolute_import
try:
    str=unicode
except NameError:
    pass

然后按照py3k的方式写程序。对于某些被重命令的库要处理一下。比如

try:
    import xmlrpclib as xrc
except ImportError:
    import xmlrpc.client as xrc

open()别用了,改用io.open()

其它的细微差别,多读一下py3k的"what's new"基本上搞定

类型:Python,创建时间:一月 1, 2012, 5:32 p.m. 点击查看完整内容。。。
编译Python源代码

在日常生活中,Python代码一般是不编译的,几个py文件复制来就能用。再加上脚本语言的名头,有些不太了解Python的朋友就以为Python没有编译这个过程。其实,虽然Python是脚本语言,但它与Java和C#一样,只能执行字节码。只是Python将编译过程隐藏起来,不大明显而已。今天这篇笔记详细记述一下Python的编译过程以及一些技巧:

  1. "优化"编译后的字节码。
  2. 禁止生成".pyc"文件。
  3. "反编译"Python字节码。
类型:Python,创建时间:一月 1, 2012, 5:05 p.m. 点击查看完整内容。。。
一个判断密码强度的函数
def judgePasswordStrength(password):
    strengthLength = max(0, len(password) - 5)
    from string import ascii_lowercase, ascii_uppercase, digits, punctuation
    flags = [bool(set(password) & set(s)) \
            for s in [ascii_lowercase, ascii_uppercase, digits, punctuation]]
    return min(flags.count(True), strengthLength)
类型:Python,创建时间:一月 1, 2012, 4:55 p.m. 点击查看完整内容。。。
(翻译)为什么Python的字符串是不可变对象

翻译自http://effbot.org/pyfaq/why-are-python-strings-immutable.htm

不可变对象是指一旦生成后不能被改变的对象。他经常与可变对象相提并论。比如Python的tuplelist,它们的行为有点类似。但是可以list对象内添加新的元素。而tuple则不可以。Python的字符串被设计成不可变对象有几个优点。

首先,可以提高性能。假定字符串是不可变对象,意味着字符串具有确定而不可变的存储需求,解释器可以为它分配一段固定的内存。这也是为什么要分为tuplelist两种类型的原因之一。让字符串成为不可变对象还可以让解释器重用该对象。比如,CPython在实现中预先申请了所有的单字节节符,并且,如果字符串运算后的结果与运算前相同,就会返回运算前的字符串(*)。

另外,在Python里,字符串就像数字一样,被认为是表示思想的最基本的材料。在Python里,没有任何方法可以把数字8变成其它东西,同样,也没有办法把"eight"这个字符串变成其它东西。

另外,使用不可变数据结构(immutable data structures),比如字符串,元组,强调了一种无副作用的编程方式。采用这种编程方式所编写的函数接收输入的参数,进行运算,然后返回一个容纳结果的新对象。而不是修改输入的参数,使它变成运算结果。当然了,有时候必须做一些有副作用的操作,比如修改对象的状态。这种事最好仔细考虑一番,因为无副作用的编程哲学能够让你的代码更加模块化,使其独立于其它代码。

类型:Python,创建时间:一月 1, 2012, 4:50 p.m. 点击查看完整内容。。。
Qt窗口的删除、析构

Qt内关于窗口的删除是一个复杂的事情。接下来详细地讲一讲。

当我们创建一个窗口时,如果这个窗口是一个顶级窗口,准确地说是w.windowFlags().testFlag(Qt.Window) is True的窗口,Qt会自动附加一个Qt.WA_QuitOnClose属性。它的意思是,窗口被关闭了,qApp.lastWindowClose信号会被触发。

默认情况下,qApp接收到此信号后会退出程序,这个行为相当于在初始化程序时:

qApp.lastWindowClosed.connect(qApp.quit)

要修改这个默认行为,可以设置QApplicationquitOnLastWindowClosed属性,比如:

qApp.setQuitOnLastWindowClosed(False)

通常,用户可以点击窗口的关闭按钮关闭窗口,或者当系统关闭的时候,窗口也会被关闭。我们可以通过重载窗口的closeEvent()函数控制关闭动作,比如询问用户要不要保存文档,或者只是最小化窗口。下面是一个例子:

def closeEvent(self, event):
    if self.maybeSave():
        self.saveSettings():
        event.accept()
    else:
        event.ignore()

我们也可以在菜单里设置一个退出命令,点击它的时候调用窗口的close()函数即是关闭窗口。

关闭窗口之后,通过我们还要手动销毁这个窗口,释放它所占用的内存。对此Qt提供了一个简便的办法,只要将窗口的Qt.WA_DeleteOnClose属性设置为true,Qt会自动帮我们销毁这个窗口。

类型:Python,C++ & Qt4,创建时间:一月 1, 2012, 4:42 p.m. 点击查看完整内容。。。