设计一个python with语句程序从文件中读取 SQL 语句

django 查看相关的sql语句-python-电脑编程网django 查看相关的sql语句作者:佚名 和相关&&django的处理就好比一 个黑盒。里面进行什么处理全部被django orm封装的比较死,可能有的时候你的程序速度比较慢,或者你想调试它的时候却不知道它里面流程,这对我们来说是件很郁闷的事情,程序员大部分都有一个好 奇的心理,都想看看里面到底是怎么执行的,不用着急,下面有个办法就很好的解决这个问题,可以让你很清楚看到django orm是执行sql语句的过程,这对我们写程序也比较有数。具体步骤:如果想要了解django 打印sql语句,可以看下这里用到了django中间件的process_response(self, request, response)方法,下面的是代码:from django.db import connectiondef process_response(self, request, response):for sql in connection.queries:print sqlreturn response如果你是用 django 自带的,就可以在SHELL里看到结果了。有了这个方法的话,你对django执行sql语句心理就有数了。如果你玩django玩的比较熟练的话,建议可以买款 主机来练习下。。原创文章请注明转载自老王,本文地址:/post/118.html作者:老王@python&python 教程老王python,提供pythn相关的python 书籍,django 教程和python下载,希望大家能够喜欢!相关资料:|||||||django 查看相关的sql语句来源网络,如有侵权请告知,即处理!编程Tags:                &                    前几天在我高高兴兴地想使用Ado访问后台 Informix 数据库时我遇到的一个编码的问题,一直没有解决。IBM Informix Client SDK 也是装了几个版本进行测试都是不行,最后为了时间上能够完成我的工作,我最终还是选择了使用Java 的 JDBC 来实现我的功能,虽然我不能在
中无缝的调用,但多少也解决了我的问题。其实使用Java只花了我几个小时,但Ado/ODBC却花费了我几天时间,也不知道这时间花得值还是不值。仔细想一想,使用Ado不仅要安装的软件多,配置工作量也多一些,远没有Java方便。Jpype也没有用起来。GCJ+SWIG感觉有些麻烦。不过从跨平台上看Java的确是方便,完全独立于操作系统,安装调试也更方便一些。我想 Python + Java 也许是更让人满意吧。不过,希望可以找到更好的互操作的方式。
— limodou @ 8:07 pm
上网就是有趣,这不在 .list 中看到一则消息,那就是美国芝加哥
用户组开会的通知,其中有一则是说一个叫的家伙会对一个叫的web framework作一个预告。
为什么说有趣呢?因为我的确发现了有趣的东西:
Django是一个尚未发布的 Python web framework。上到它的主页几乎没有什么东西,好象是在找律师商量关于代码发布的版本问题。这个月应该可以发布。同时我在网上找到它在 Python.org 的wiki上有一个,下面是它的描述: is a high-level Python Web framework that encourages rapid development and clean, MVC design. Includes a template system, object-relational mapper and a framework for dynamically creating admin interfaces.Django是一个高级 Python web framework,它鼓励快速开发和干净的、MVC设计。它包括一个模板系统,对象相关的映射和用于动态创建管理界面的框架。Django has been actively developed over the past year and a half. Ruby on Rails is similar to it, but Django is written in Python and has a few more advanced conveniences for super-quick Web development. Django已经积极开发了一年半了。Ruby on Rails与之相似,但Django是用 Python 编写的,对于超快的web开发有一些更高级的便利。This framework is a potential competitor for Rails. It can claim one high profile site so far, chicagocrime.org though the same was true of Rails when the hype started. If Adrian Holovaty and Simon Willison blog about it and evangelize it in the same way that DHH did for Rails and the meme manages to propagate across the blogosphere, Django may achieve a similar profile. A big win for Rails was the accompanying documentation, the very active wiki and the screencasts. This made it much more approachable for interested web developers to get started.这个框架对于Rails是一个潜在的竞争者。迄今为止它可以声明一个站点的高层轮廓,可是在作此番宣传的时候,chicagocrime.org对于使用Rails来说也是一样可以做到的。如果Adrian Holovaty和Simon Willison写Django的Blog,并且象DHH对待Rails一样来对它进行传教式的宣传,并且跨越blog群体进行宣传,Django也许可以获得相似的地位。对于Rails的一个大胜利就是公司列表文档,非常活跃的wiki和屏幕展示。这样使得它对于想要开始进行web开发的开发者更感到容易接受。(翻译水平有限,凑和着看吧:)
chicagocrime.org就是使用Django开发的。同时在Django的项目主页上还有一些使用Django开发的网站,看上去都不错。那么这个chicagocrime.org是芝加哥犯罪情况的网站,让人感兴趣的是在首页有一个map,如果你点击进去,你会看到它使用了google map的功能,但是它增加了自已的东西。google已经公布了map的api,因此你完全可以使用它,这就是一个很好的例子,真是利害。
这个叫Adrian Holovaty研究google map已经有几个月了,颇有心得,看看他的Blog就知道了。
在我看他的Blog的时候,我发现他就是编写Creasemonkey compiler的人。Creasemonkey是Firefox的一个扩展,它可以安装脚本,用于在客户端修改得到的页面。功能超强。如果你不知道Greasemonkey,那么建议你到网上搜一搜吧。那么这个编译器就是可以把需要依赖Creasemonkey才可以运行的脚本可以变成可以单独安装的Firefox扩展,因此受到不少人的欢迎。
看到这些真是对Django很期待,很想看一看,到底它能达到Ruby on Rails一样的功能,甚至更好吗?发现的东西真是很有趣,好象不相干的事情都联系在一起了。
— limodou @ 9:59 pm
二、使用Adodbapi来操作Ado
在上面我们已经配置好了Informix的ODBC客户端,同时也应该已经测试连通成功。如果在配置时报告了Informix的错误代码,可以到CSDK的安装目录下的bin子目录中,找到FindErr程序。它是一个帮助文件,可以用来查找出错码。
然后我们到
的主页上下载这个包,然后安装它。既然它支持DB 2.0 Api那么所有的标准操作都是支持的。那么简单的操作与使用
使用connect()与数据库进行连接
使用连接对象的cursor()来创建一个游标
然后调用游标的execute()来执行SQL操作
再调用fetchone()或fetchall()来得到结果
那么这里的重点其实在连接上,connect()需要一个连接字符串,这个串的写法需要符合odbc的要求,写法可能很多,但我只试了简单的用法:
cx = connect(r&Dsn=Database=UID=PWD=password&)
上面Dsn就是前面所创建的用户Dsn。这里指定了Dsn名、数据库名、用户名和口令。这样就通过设定好的数据源与后台数据库联起来了。
剩下大家就可以使用DB 2.0 API进行测试了。
不过这里有一个很特殊的情况在我的环境中,就是我在前面所说的:后台数据库使用的是utf-8编码的。当我通过Ado得到返回的字符串数据时,我得到的都是unicode,但当我打印它们时,都是乱码。于是我猜想它们是被错误编码了。于是我使用下面的方法来转码:
def convert(s):&&& return unicode(s.encode(‘cp936′), ‘utf-8′)
也就是先按GB码解码,然后再按UTF-8编码成Unicode。结果再打印就对了。我也不知道到底是哪里出的问题,配置也还不会改,只好先这样处理了。如果后台使用GB码来存储的话,可能就没有这个问题了。那么在写回数据库时我还需要反向转回来。虽然有些麻烦,但是先用上再说。
对于数据库编码的问题我还怀疑是不是我使用的 adodbapi 有问题呢?但当我按教程直接使用 Ado 对象来得到数据时,结果是一样的,看来还是配置的问题,以后再慢慢解决吧。如果有知道的请告诉我呀。
— limodou @ 9:54 pm
项目的后台系统使用的是Informix,而我使用
开发了一个客户端软件,它是用来进行标准数据维护的。现在我希望实现的是把本地的数据更新到后台的 Informix 服务器中去。那么我原先想使用 Jdbc 来访问,因为已经有现成的程序可以做这件事,于是我想使用
来做这件事,但试了半天,再加上没什么文档和例子,又似乎不稳定,终于不知道该怎么办,于是我放弃了。终于想通过 Ado/Odbc 来处理了。
关于Ado的文档网上也已经有了,这里有一个老外写的不错的教程《》,以前也介绍过。不过,网上还有一个 Adodbapi 的符合 DB 2.0 – API 的模块可以使用,它比起直接访问Ado要方便得多,我主要是使用 adodbapi& 来处理,但为了测试也会使用 win32com 来直接访问 com 对象来处理。
一、在Windows上安装 Informix cli odbc 驱动程序并配置
有了驱动程序(没有的话可以到下载,里面有开发版和连接版。Windows平台下使用其中有Win的文件,下载CSDK就是开发版),安装很简单,我安装的是SDK版本。安装好后,在 ODBC 的管理中可以看到驱动程序页多了 IBM Informix&3.82 32 BIT的驱动程序,这样说明安装成功了。
下面开始配置ODBC了。配置它可费了牛劲了。说实在的,以前直是没有配过类似的东西,都是一点点地在网上查文档,做试验。等我做完了竟然发现了这么一篇文档《》,晕死。
在我的配置经历中在客户端主要的配置为(我的系统是Windows XP):
修改 C:\WINDOWS\SYSTEM32\DRIVERS\ETC 下的HOSTS文件,增加服务器主机地址和名字
修改 C:\WINDOWS\SYSTEM32\DRIVERS\ETC 下的SERVICES文件,增加后台Informix的services的入口,主要为:服务名称&&& 端口/协议。要注意这个配置与后台Unix中的/etc/services的配置要一样。
在ODBC数据源中增加一个用户Dsn。具体配置可以按上面的文档操作,虽然没仔细看,但感觉差不多。增加后作一下测试,如果成功则没有问题了。
其中Informix的安装目录下还有一些配置和测试工具,如:setnet32可以用来配置,不过好象不需要。我用它配置过,但后来出错了,结果重装驱动,还有问题,不得已,手工在regedit中大删了一把,把所有与Informix粘边的东西全部删除,再重装就行了,搞不懂啊。ilogin可以用来测试与后台连接。不过使用ODBC中的测试就够了。
现在Informix支持GLS(Global Language Support),但我在ODBC中不知道怎么设中文。在我的应用中很奇怪,后台Informix使用的是utf-8编码。DB_LOCALE和CLIENT_LOCALE配成zh_CN.gb好象不行,总报错,后来还是使用缺省的编码了。当然是有问题的,这个以后再说。
对了,要使用Ado来访问数据库,当然要安装Ado的服务程序,在网上搜搜MDAC吧,应该可以找到比较新的版本。
— limodou @ 5:42 pm
在继上一篇文章之后,我继续努力了一下,希望让结构更好一些,代码如下:
#coding=cp936
import wximport timeimport threadingimport Queueimport tracebackimport sys
class MainApp(wx.App):
&&& def OnInit(self):&&&&&&& self.frame = MainFrame()&&&&&&& self.frame.Show(True)&&&&&&& self.SetTopWindow(self.frame)&&&&&&& return True
class MainFrame(wx.Frame):
&&& def __init__(self):&&&&&&& wx.Frame.__init__(self, None, -1, u’长运行测试’)
&&&&&&& box = wx.BoxSizer(wx.HORIZONTAL)
&&&&&&& self.ID_BTN = wx.NewId()&&&&&&& self.btn = wx.Button(self, self.ID_BTN, u’开始’, size=(60, 22))&&&&&&& box.Add(self.btn, 0, wx.ALIGN_CENTRE|wx.ALL, 0)&&&&&&& &&&&&&& self.ID_STOP = wx.NewId()&&&&&&& self.btnStop = wx.Button(self, self.ID_STOP, u’停止’, size=(60, 22))&&&&&&& box.Add(self.btnStop, 0, wx.ALIGN_CENTRE|wx.ALL, 0)
&&&&&&& wx.EVT_BUTTON(self.btn, self.ID_BTN, self.OnStart)&&&&&&& wx.EVT_BUTTON(self.btnStop, self.ID_STOP, self.OnStop)&&&&&&& &&&&&&& self.SetSizerAndFit(box)&&&&&&& &&& def OnStart(self, event):&&&&&&& progress = ProgressViewer(100)&&&&&&& self.controller = Controller(run, progress)&&&&&&& self.controller.start(100, self.controller)&&&&&&& &&& def OnStop(self, event):&&&&&&& dlg = wx.MessageDialog(self, u’是否停止打印?’, u’消息’, wx.YES_NO | wx.ICON_INFORMATION)&&&&&&& if dlg.ShowModal() == wx.ID_YES:&&&&&&&&&&& self.controller.setStop()&&&&&&& PROCESS_MESSAGE = ‘process’EXCEPTION = ‘excpetion’
class Controller:&&& def __init__(self, processor, viewer):&&&&&&& self.processor = processor&&&&&&& self.viewer = viewer&&&&&&& self.message = Queue.Queue()&&&&&&& self.runFlag = True&&&&&&& &&& def start(self, *args, **kwargs):&&&&&&& self._thread = threading.Thread(target=self.processor, args=args, kwargs=kwargs)&&&&&&& self._thread.start()&&&&&&& self.viewer.setController(self)&&&&&&& self.viewer.start()&&&&&&& try:&&&&&&&&&&& while 1:&&&&&&&&&&&&&&& try:&&&&&&&&&&&&&&&&&&& cmd, message = self.message.get_nowait()&&&&&&&&&&&&&&&&&&& if cmd == PROCESS_MESSAGE:&&&&&&&&&&&&&&&&&&&&&&& self.viewer.process_message(message)&&&&&&&&&&&&&&&&&&& elif cmd == EXCEPTION:&&&&&&&&&&&&&&&&&&&&&&& print ‘Exception’&&&&&&&&&&&&&&&&&&&&&&& traceback.print_tb(message)&&&&&&&&&&&&&&&&&&&&&&& break&&&&&&&&&&&&&&& except:&&&&&&&&&&&&&&&&&&& pass#&&&&&&&&&&&&&&& self._thread.join(0.1)&&&&&&&&&&&&&&& if not self._thread.isAlive():&&&&&&&&&&&&&&&&&&& break&&&&&&& finally:&&&&&&&&&&& self.viewer.stop()&&&&&&& while not self.message.empty():&&&&&&&&&&& cmd, message = self.message.get_nowait()&&&&&&&&&&& if cmd == EXCEPTION:&&&&&&&&&&&&&&& print cmd, ”.join(message)&&&&&&& &&& def ack(self):&&&&&&& if not self.runFlag:&&&&&&&&&&& raise Exception&&& &&& def send_message(self, cmd, message):&&&&&&& self.message.put_nowait((cmd, message))&&&&&&& &&& def setStop(self):&&&&&&& self.runFlag = False&&&&&&& class BasicViewer:&&& def __init__(self):&&&&&&& pass&&& &&& def process_message(self, message):&&&&&&& pass&&& &&& def start(self):&&&&&&& pass&&&&&&& &&& def stop(self):&&&&&&& pass&&&&&&& &&& def setController(self, controller):&&&&&&& self.controller = controller&&&&&&& class ProgressViewer(BasicViewer):&&& def __init__(self, number):&&&&&&& BasicViewer.__init__(self)&&&&&&& self.number = number&&&&&&& self.progress = None& &&& def process_message(self, message):&&&&&&& if self.progress:&&&&&&&&&&& flag = self.progress.Update(message)&&&&&&&&&&& if not flag:&&&&&&&&&&&&&&& self.controller.setStop()
&&& def start(self):&&&&&&& self.progress = wx.ProgressDialog(u&运行…&, u&正在处理请稍候…&, self.number, style=wx.PD_AUTO_HIDE|wx.PD_CAN_ABORT)&&&&&&& &&& def stop(self):&&&&&&& if self.progress:&&&&&&&&&&& self.progress.Destroy()&&&&&&&&&&& self.progress = None&&&&&&& def run(number, controller):&&& for i in range(number):&&&&&&& print ‘run %d’ % (i+1)&&&&&&& controller.send_message(PROCESS_MESSAGE, i+1)&&&&&&& try:&&&&&&&&&&& controller.ack()&&&&&&& except:&&&&&&&&&&& controller.send_message(EXCEPTION,traceback.format_exception(*sys.exc_info()))&&&&&&&&&&& break&&&&&&& time.sleep(0.1)&&& app = MainApp(0)
app.MainLoop()
那么这个程序与前一个程序有什么区别呢?主要是将GUI显示独立出来,有一个BaseViewer的基类,定义了一些基本的操作方法。同时我派生了一个状态条的ProgressViewer类,专门用来显示进度条。这样,整个框架变成了:Controller, Processor, Viewer,基本上满足了MVC的架构了。同时一个大的变化就是由Controller来控制消息的处理,它将从队列读取消息。但这里有一个问题,如果只是简单的消息处理是不够的,因此又开发了简单的协议控制。因此队列中的每一条消息是一个(命令,消息)的二元tuple。Controller读出消息后,根据命令的不同,或者向Viewer发送消息,或者作特殊处理。这里我只处理了异常,因为只是测试,大家如果有兴趣可以去扩充。同时我还注意到,当处理线程退出时,很有可能队列中还有一些消息。因此我在Controller的循环退出之后,又增加了对队列的处理。那么在这个处理中,我丢掉了可能的进度变化的消息,只是显示了可能的异常信息。不过,这里对异常封装得简单,做得好的话可以在Controller中增加返回异常消息的方法,可以由Processor来调用。Viewer是一个对象,但Processor为了简单我还是使用了函数,并且没有对调用的参数作进一步规范。因为每个应用的情况千差万别,适合自已就可以了,基本框架都是可以改的,重要的是方法。
运行上面的程序你还会发现,主窗体增加了一个&停止&按钮。增加它的目的就是为了测试:在我运行一个长处理时,线程可能运行得非常好,问题时我还可以做别的吗?因为不难看出,上面的Controller的start()基本上是一个循环,在这个循环没有退出,别的GUI的元素还可以继续处理吗?这就是我为什么加上&停止&按钮的原因。测试结果是没有问题。具体的原因我没有细查,我想与队列与判断线程是否活动的处理有关, 当然只是一个测试,对于我来说可用就行了。知道为什么固然好,不知道能用也是不错的。如果有知道的,一定别望了告诉我为什么:)
如果再对这个框架进一步优化的话,那么可以考虑以下几点:
多线程的处理
考虑将线程设为deamon,这样退出时可以自动关闭
— limodou @ 6:56 pm
GUI 编程我已经做了很多,但一直很难处理的一个问题就是:如果我有一个长时间的处理,我希望在它处理时窗口不会被锁住。我想要实现这一点线程是少不了的,因此带有这个问题,我从 google 上找到了一篇文章《》,这篇文章我觉得非常好,它的例子是使用Tkinter来编的。
那么先谈一谈我对这篇文章的理解。这篇文章好在不仅有讲解,而且还有完整的源程序可以运行,让你亲身感受到处理的效果。只不过它的例子在我看来还是有些复杂,因此我自已也编了一个示例程序,应该相比之下更要简单得多。
那么这篇文章所讲述的关键之处在于通过一个连接器connector来连接长处理与GUI显示部件之间的协作。
对于连接器,它使用线程将长处理包装起来,并且在调用长处理时将connector与一个进度控制器传入,这样需要长处理在处理过程中一方面根据约定来调用进度控制器的方法,将进度发送出去,另一方面要调用connector的应答方法来控制自身的运行状态。那么这两个处理,对于整个过程是一种约定。同时链接器还控制着GUI显示部件的刷新,因为GUI的处理需要在主线程中处理为好。这样就存在两个线程的运行,同时长处理线程控制着进度的变化,如何将进度的变化通知给主线程来更新GUI部件这是一个很重要的处理。原例子中使用了队例(Queue)来处理。但是在长处理中并不直接使用队例,这个队例的创建也是由connector来完成,在进度控制器中完成将进度变化写入队列中。然后在主线程中读取队列得到变化值,然后更新GUI的进度。在原例子中等待长处理线程的完成是通过延迟执行来循环等待的。也就是在判断出线程仍在继续运行后,调用after()方法,在某个间隔时间之后再进行状态的检查,直到线程的结束。现在对Tkinter已经忘记差不多了,因此也不清楚after()是不是Tkinter的系统方法,总之大概就是这个意思。
上面的思想经过我的简化可以总结为:
整个处理基本上分为两个部分:controller和processor。
controller用于线程包装,Queue的创建,启动processor线程,接收processor线程按约定发出的信息并进行GUI的显示处理,还要等待processor线程的结束。
而processor相对处理简单,调用信息发布处理函数,调用用于进程控制的应答处理。信息发布函数将利用队列来与主线程进行通讯,可以完成象进度改变,状态改变这样的信息传递。应答处理是controller的方法,它可以根据外部的控制来返回相当的控制信息供线程来使用,如:是否结束处理等。
那么我也写了一个示例程序,这个程序只有一个文件,它使用wxPython作为它的GUI环境。它的处理过程就是:程序运行后,主窗口上有一个&开始&按钮,点击运行后,会在dos窗口中不停打印从1到100的数。同时在运行时会有一个进度窗口,它会显示打印的进度,一旦到达100,线程结束,进度窗口也消息。同时在运行时,用户可以点进度窗口上的&取消&按钮从而结束打印过程,用户可以在dos窗口中看到引发了一个异常。整个运行过程主窗体可以拖动,没有无响应的情况。程序如下:
#coding=cp936
import wximport timeimport threadingimport Queue
class MainApp(wx.App):
&&& def OnInit(self):&&&&&&& self.frame = MainFrame()&&&&&&& self.frame.Show(True)&&&&&&& self.SetTopWindow(self.frame)&&&&&&& return True
class MainFrame(wx.Frame):
&&& def __init__(self):&&&&&&& wx.Frame.__init__(self, None, -1, u’长运行测试’)
&&&&&&& self.ID_BTN = wx.NewId()&&&&&&& self.btn = wx.Button(self, self.ID_BTN, u’开始’, size=(60, 22))&&&&&&& &&&&&&& wx.EVT_BUTTON(self.btn, self.ID_BTN, self.OnStart)&&&&&&& &&&&&&& self.Fit()&&&&&&& &&& def OnStart(self, event):&&&&&&& controller = Controller(100, run)&&&&&&& controller.start()
class Controller:&&& def __init__(self, number, func, *args):&&&&&&& self.func = func&&&&&&& self.number = number&&&&&&& self.message = Queue.Queue()&&&&&&& self.flag = True&&&&&&& &&& def start(self):&&&&&&& self._thread = threading.Thread(target=self.func, args=(self.number, self))&&&&&&& self._thread.start()&&&&&&& self.progress = wx.ProgressDialog(u&运行…&, u&正在处理请稍候…&, self.number, style=wx.PD_AUTO_HIDE|wx.PD_CAN_ABORT)&&&&&&& try:&&&&&&&&&&& while 1:&&&&&&&&&&&&&&& try:&&&&&&&&&&&&&&&&&&& n = self.message.get_nowait()&&&&&&&&&&&&&&&&&&& self.flag = self.progress.Update(n)&&&&&&&&&&&&&&& except:&&&&&&&&&&&&&&&&&&& pass#&&&&&&&&&&&&&&&& self._thread.join(0.1)&&&&&&&&&&&&&&& if not self._thread.isAlive():&&&&&&&&&&&&&&&&&&& break&&&&&&& finally:&&&&&&&&&&& self.progress.Destroy()&&&&&&& &&& def ack(self):&&&&&&& if not self.flag:&&&&&&&&&&& raise Exception&&& &&& def process(self, number):&&&&&&& self.message.put_nowait(number)
def run(number, controller):&&& for i in range(number):&&&&&&& print ‘run %d’ % (i+1)&&&&&&& controller.process(i+1)&&&&&&& controller.ack()&&&&&&& time.sleep(0.1)&&& app = MainApp(0)
app.MainLoop()
这里Controller是处理器,run是长处理,它会调用Controllor的process()来改变进度。调用Controllor的ack()来自动处理线程的中断。这里ack()在判断出用户中断了处理后,会引发一个异常。这样当run()在循环中调用它时会引发异常而中止。在你的处理中完全可以不使用异常,而是主动判断状态,方法都是可以的。使用异常是最简单的方法。controllor的process()处理是向共用的mssage队列中发消息,用来发布进度的状态。那么对于processor的线程控制就是:
&&& def start(self):&&&&&&& self._thread = threading.Thread(target=self.func, args=(self.number, self))&&&&&&& self._thread.start()&&&&&&& self.progress = wx.ProgressDialog(u&运行…&, u&正在处理请稍候…&, self.number, style=wx.PD_AUTO_HIDE|wx.PD_CAN_ABORT)&&&&&&& try:&&&&&&&&&&& while 1:&&&&&&&&&&&&&&& try:&&&&&&&&&&&&&&&&&&& n = self.message.get_nowait()&&&&&&&&&&&&&&&&&&& self.flag = self.progress.Update(n)&&&&&&&&&&&&&&& except:&&&&&&&&&&&&&&&&&&& pass&&&#&&&&&&&&&&& self._thread.join(0.1)&&&&&&&&&&&& if not self._thread.isAlive():&&&&&&&&&&&&&&&&&&& break&&&&&&& finally:&&&&&&&&&&& self.progress.Destroy()
它使用threading.Thread()来封装长处理(run),同时传入自身。对于从队列取消息,然后更新进度的处理,就直接在启动processor线程之后进行。它与等待线程结束的处理放在了一个while循环中:有消息则处理,没有消息就等待线程结束。如果线程结束就退出,否则继续处理。因此这里与原程序是不同的,但想要达到的目前是一样的。其实在wxPython也有象CallAfter()的方法可以延迟执行,但没有试。
整个示例程序可能适用于等待一个长时间处理完成的情况。对于多线程需要改造可能才能使用,但基本思想不外乎:长处理使用线程,GUI的改变在主线程中完成,线程之间使用队列来通讯,控制器来绑定相关的资源和状态。
上面的例子,控制器除了监控线程的结束,还起到了修改GUI状态的功能,这只是为了程序简短,其实也可以象原程序一样增加一个GUI显示处理器,将GUI状态的改变这部分功能独立出来,这样控制器的功能更加清晰,更且有通用性。
— limodou @ 4:02 pm
关于对象的复制,如列表经常会有人搞不太清楚,为了解决这个问题,我在网上找到两篇文章:
&《》& 《》
关于这个问题我的一些体会如下,写得匆忙,可能还有问题。
&如果真想搞清楚的话恐怕要看Python的源码了,不过我想我们只要了解在Python中对象与名字绑定这些概念,再加上对一些特例情况的理解应该就可以了。因为我们平时更关心的是值的变化。简单地总结一下,有没想到的大家可以补充:1. 对于可变对象要注意是新对象还是对象的引用。比如列表重复a = [1,2,3]b = [a]*3得到的是对a的n次引用,而不是创建了n个新对象。如果我们是只读的处理,因此无所谓,但如果要修改它们的值,而且不能相互影响,这样需要创建对象的拷贝,如:b=[a[:] for i in range(3)]a[:]是创建一个不同于a的新对象。而使用list comprehension 是用来执行3次这样的创建过程。(暂时只想到这个方法)对于可变对象的复制如果只是读操作,则直接赋值即可,但如果想用于以后修改,但又不想影响原来的对象,则需要进行复制。list 可以使用a[:]这样的处理,但如果一个列表中的元素还存在可变对象,如列表中的列表,则上面的方面不能解决问题,需要使用copy模块中的deepcopy来解决,这就是深度拷贝。它的作用就是将一个对象的所有元素,包括这些元素的子元素也都创建出新的对象,而不是原来对象的引用。其中可变对象为:list, dict, object2. 对于函数的参数缺省值的使用。如果是可变参数为作缺省参数,要注意,当函数在编译时缺省参数被创建,并被保存在某个地方。这个创建过程一般只执行一次。而这样的话造成这个可变的缺省值一旦被改变,当函数再次执行值,它的值仍然被保存起来了,而不会重新初始化。这样有时会产生一些问题。但有时却的确有用。那么从上面的简单分析可以看出,如果对象是用来读的,不会有问题。问题就出现在读写上。因此对于修改一个可变对象的值时就需要注意这个问题的。那么再分析一下,这此问题基本上可以归结为:1.变量复制如果想修改原对象,那么直接修改就行了,因为这正是你想要的。如果的确是想创建一个新对象,不想影响原来的对象,那么要么使用浅拷贝,要么使用深拷贝,关键是看对象的复杂程度了。2.缺省值是可变对象如果不想使用这个可变对象参数来作一些特殊的事,还是不要用得好。使用None或其它的非可变对象。我想基本上容易出问题的就是这两个地方吧。
— limodou @ 8:49 pm
在发现 xlrd 之后不久就发现了
,它与 xlrd 不同,它主要是用来写 Excel 文件,当然读也是没有问题的。下面就它的使用简单地介绍一下。
一、Excel文件读取
from pyExcelerator import *sheets = parse_xls(‘d:/a.xls’)
很简单,与 xlrd 不同。xlrd 需要先调用book = xlrd.open_workbook(filename)打开文档,然后再调用sh = book.sheet_by_index(i)来得到第几个sheet,然后再使用sh.cell_value(i, j)得到i行j列的单元格的值。操作多了一点。而上面的parse_xls(filename)则直接返回一个列表,每一项就是一个sheet的数据。每项是一个二元组(表名,单元格数据)。其中单元格数据为一个字典,键值就是单元格的索引(i,j)。如果某个单元格无数据,那么就不存在这个值。看似简单,但从处理上不象 xlrd 一样,可以知道每个sheet的最大行数和列数,然后进行循环。而使用 pyExcelerator 好象没有最大行数和列数,再加上空数据又不存在,因此在处理上相对麻烦一些。这样在处理上还需要注意。它与 xlrd 一样都支持 unicode ,但好象没有 xlrd 一样方便地判断单元格的类型的方法,感觉还是 xlrd 在功能上可能要强一些。当然这只是个人感觉,再加上只是看了看例子,并没有怎么使用。
二、Excel文件写入
这个才是重头。那么安装好 pyExcelerator 之后,读了 Readme.txt 之后了解到它的文档正在进行当中,因此想多了解如何使用它需要看它所带的例子,甚至看源程序。下面是我从例子中了解的如何写一个 Excel 文档需要了解的。
为了方便,在导入这个模块中使用了import *的方式。
from pyExcelerator import *
首先导入模块,然后是生成工作薄。
w = Workbook()
接着是加入一个工作表(sheet)。
ws = w.add_sheet(‘Hey, Dude’)
然后就可以保存了。
w.save(‘mini.xls’)
上面的代码加在一起就是:
from pyExcelerator import *
w = Workbook()ws = w.add_sheet(‘Hey, Dude’)w.save(‘mini.xls’)
这就是最小的一个例子了,在例子中叫mini.py。你可以在例子目录下运行mini.py看一看是不是生成了一个空的Excel文件。
如果想加入中文很简单,改为:
#coding=cp936from pyExcelerator import *
w = Workbook()ws = w.add_sheet(u’这是中文’)w.save(‘mini.xls’)
这样上面的执行结果是生成一个空Excel文件,但它的第一个sheet的名字为&这是中文&。就这样,只要保证你写入时使用unicode就行了。
空文件可以生成,那么如何插入单元格呢?
ws.write(i, j, value)
其中value为值,可以是unicode。
接着,我们可能想改变单元格的样式,如字体:
font0 = Font()font0.name = ‘Times New Roman’font0.struck_out = Truefont0.bold = True
style0 = XFStyle()style0.font = font0
这样我们创建了一个字体,然后又生成了一个样式。注意,真正起作用的是样式,字体不过是样式中的一种效果。
这样在写入单元格时带着这个样式就行了,还是使用上面的write()方法:
ws.write(1, 1, ‘Test’, style0)
这是在名为ws的sheet中的第(1,1)单元格写入了值为&Test&的内容,并且它的样式为style0。
然后我们还可以设置单元格的边框:
&&& borders = Borders()&&& borders.left =&5&&& style.borders = borders
上面创建了一个边框效果,设置了左边框,至于5是什么意思,我也不清楚,随便写的。然后放到样式中。上面的例子可以参考format.py程序。
其它还有许多的效果,简单地列一下:
&col_width.py
改变单元格宽度&
&row_style.py
设置行的高度&
&merged*.py
单元格合并&
&outline*.py
大纲效果(以前真没用过)&
&wsprops.py
sheet的属性值打印&
Excel转为其它的文件格式&
大家有兴趣自已照着例子学吧。
— limodou @ 5:19 pm
最近在项目中大量使用
来生成Html文档,同时又发现它的一个方便之处,那就是模板调用模板,可以实现一种继承关系。为什么呢?因为 Meteor 最常用的模板形式其实就是
的模块,因此可以相互调用。而每一个模板变量就是一个对象。同时在模块中定义的模板变量可以与其它被导入的模板的变量同名,这样就起到覆盖变量的作用,也就是在当前模板中的变量如果与其它导入的变量重名,当前的变量会起作用。当然,如果你把导入放到最后结果正好相反,不过一般人也不会这样去做。
通过这种方法我们就可以实现一种模板的继承处理。比如先定义一个模板框架,如一个Html文档模板由:header, body, footer三部分组成。然后在不同的个性化模板可以导入这个模板框架,然后相同的部分继承过来,只要重新定义body变量即可,不用全部重写,这样对于实现有相同的头和尾的页面结构来说是非常方便的,修改也方便。这样就可以把复杂的模板或公共的模板分解成多个模板,以实现重用。
下面是一个示例:
a.py(模板文件)
from meteor import *
header = T(”’&html&&head&&title&&#title#&&/title&&/head&&body&”’)body = T(”’&h1&Hello, meteor&/h1&”’)footer = T(”’&/body&&/html&”’)html = T(”’&#header#&&#body#&&#footer#&”’)
它定义了4个模板变量:header, body, footer, html。其中由html变量将其它部分进行组装,最后形成真正的内容。
b.py(模板文件,将导入a.py)
from meteor import *from a import *
body = T(”’Hello, &#name#&”’)
重用a.py中定义的模板变量,只是修改了body变量。
c.py(测试程序)
from meteor import *
vars = {’title’:'Test’, ‘name’:'limodou’}template = Template()template.load(‘b.py’, ‘python’)print template.value(‘html’, vars)
最后的结果为:
&html&&head&&title&Test&/title&&/head&&body&Hello, limodou&/body&&/html&
很有趣吧。
为了发布程序,上面的大括号由半角改为了全角,因此做测试时请转换回来。
— limodou @ 10:09 pm
最近在我正在开发的一个数据维护工具中我经常使用
来读取Excel文件,在转换过程中一直也没有遇到什么问题,只不过需要注意,它返回的字符串都是 Unicode 编码。不过今天在使用时发现对于日期类型,在Excel文件中看到的可能是 && 这样格式,但直接使用 xlrd 来读的话却会变成 38541。很奇怪。仔细查看 Excel 后再经过试验,我明白了 Excel 保存日期其实是使用一个长整数,只不过显示时可以为标准的日期格式。本来我想将日期在 Excel 中直接转为日期格式的字符串,但没整出来,而且我更希望有一种方法可以正确地进行转换。于是我想 xlrd 有没有这样的处理呢?使用
的代码提示功能,查了查 xlrd 模块的属性,没找到。不过看到它有cell_type(i, j)的方法可以返回一个单元格的数据格式。于是我使用这个方法打出日期所在的单元格的格式为:3。然后又比较了 xlrd 中定义的一些常量,最后锁定在了 XL_CELL_DATE上,它的值就是 3。这样到目前为止我已经知道了如何判断一个单元格是否是日期类型,下面就是如何转换了。
我查阅了datetime 模式,在它的date类中查到一个函数叫:
fromordinal(oridnal)
它的作用是将从公元1年1月1日开始的天数转换为年月日的形式。于是我试了一下:
&&& import datetime&&& datetime.date.fromordinal(38541)datetime.date(106, 7, 10)
好象不对呀。于是我反向转转试试:
&&& datetime.date.toordinal(datetime.date())732135
怎么这么大的数。后来我想到可能fromordinal与Excel使用的起始日期可能是不同的。做个减法看一看是哪天。
&&& datetime.date.fromordinal(732135 &# + 1)datetime.date()
原来如此,是
日,这回我明白了。其实象用过的 Informix 中的日期与 Excel 的方法是一样的,都是从
开始计算的。那么做个转换函数吧:
__s_date = datetime.date().toordinal() – 1def getdate(date):&&& if isinstance(date, float):&&&&&&& date = int(date)&&& d = datetime.date.fromordinal(__s_date + date)&&& return d.strftime(&%Y-%m-%d&)
上述函数就是用来将一个从
开始计算的天数转成年月日的格式,并且是字符串的形式。其中如果传入的是一个浮点数,先取整再进行转换。
— limodou @ 9:24 pm
本站所有内容采用许可证。
Pythoner in 中国
Python开源项目
我的开源项目}

我要回帖

更多关于 python输入语句 的文章

更多推荐

版权声明:文章内容来源于网络,版权归原作者所有,如有侵权请点击这里与我们联系,我们将及时删除。

点击添加站长微信