2010年7月9日星期五

Python中的交互

先对内容说明一下,手头是2.6的版本,考虑兼容2.5。
主要参考与来源是Python的文档,只选择性地涉及了部分库,而且没有去标注版本变动。
以下内容只是做了一个相当简略的归类性质的东西,也算是概览之类的吧。
本帖算是选定了一个话题,就是列举一下Py对常见的交互方式的实现。
暂时只列举了一些目前容易想到的方式,并略做了说明。


command

sys.argv是一个list类型的实例,argv[0]是脚本的名称的字符串。
如果要处理流的重定向的话用FileInput
import fileinput;for line in fileinput.input():process(line)

getopt(或optparse)则用于解析Unix风格的命令行参数。


stdio

print和input这一组的表达为:
"print" ([expression ("," expression)* [","] | ">>" expression [("," expression)+ [","])
raw_input([prompt])

较底层的话,stdin/stdout/stderr都在sys里面,依照File对象使用。
有getpass用于输入密码。


file

内置的open函数返回一个File对象。
StringIO模块可用于实现内存文件。
其他的文件操作在os模块中。
还有一个io模块是后来增加的。
一些交换用的文件格式有专门的模块。


process

原本在os模块里,后来单独为subprocess模块了。


socket

这是较底层的可用于网络通讯接口,以下也将仅涉及这一方面。

客户端
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect(("www.google.com", 80))

服务器
serversocket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
serversocket.bind((socket.gethostname(), 80))
serversocket.listen(5)
while 1:
....(clientsocket, address) = serversocket.accept()
....ct = client_thread(clientsocket)
....ct.run()

数据读写都是用到send()/recv()方法

如果TCP上的HTTP协议的话,在性能要求不高的条件下,
客户端可以用urllib2模块,服务器则可用BaseHTTPServer模块提供的框架(多线程则用ThreadingMixIn结合threading模块)。
其他协议也有单独的模块来着。


curses

这是绑定了一个Unix平台下可以使用的终端界面
代码是像这个样子的:
import curses
scr=curses.initscr()
curses.echo()
curses.cbreak()
scr.keypad(1)
scr.clear()
curses.start_color()
curses.init_pair(1, curses.COLOR_RED, curses.COLOR_GREEN)
scr.attron(curses.color_pair(1))
scr.box(curses.ACS_VLINE, curses.ACS_HLINE)
scr.move(curses.LINES/2, curses.COLS/2)
scr.addstr("hello, world!")
scr.addstr(5,33, " "*43, curses.A_UNDERLINE)
scr.attroff(curses.color_pair(1))
scr.refresh()
win=curses.newwin(10,10,2,2)
win.refresh()
s=win.getstr(0,0,5)
scr.addstr(s)
text=curses.newwin(50,50,10,5)
import curses.textpad
curses.textpad.Textbox(text).edit()
c=scr.getch()
if c==ord('q'):pass
scr.keypad(0)
curses.endwin()
API主要在curses命名空间上和Window对象上。
其中curses上改变状态的操作要手动恢复,而Window对象有若干种类型。


tkinter

在Python中内置了Tk的绑定,用于显示图形界面。
先来一个Hello World
#!/usr/bin/env python
#coding:utf-8
import Tkinter as tk
#http://www.pythonware.com/library/tkinter/introduction/
#http://infohost.nmt.edu/tcc/help/pubs/tkinter/
root=tk.Tk()
w=tk.Label(root,text="Hello World")
w.pack(side=tk.LEFT)
root.mainloop()

开始主程序后,就可以创建Widget了,然后放置。
Widget属性可以用其config方法来设置。
放置Widget可以用的方法是pack,grid以及place。
然后就是事件绑定。
还一些提供有其他的东西,例如更多的Widget和一些Dialog。
以下是一个随意的示例:
#!/usr/bin/env python
#coding:utf-8
import Tkinter as tk

class App(tk.Frame):
def __init__(self,root):
tk.Frame.__init__(self,root)
self.pack()
root.protocol("WM_DELETE_WINDOW", self.closeEvent)
top = tk.Toplevel()
self.w=tk.Label(self,text="Hello World")
self.w.pack(side=tk.LEFT)
self.txt=tk.StringVar()
self.e=tk.Entry(self,textvariable=self.txt)
self.e.pack(side=tk.LEFT)
f=tk.Frame(self)
f.pack(side=tk.LEFT)
self.btn=tk.Button(f,text="change",command=self.change)
self.btn.bind("",self.change)
self.btn.pack(side=tk.LEFT)

def change(self,event=None):
self.w["text"]=self.e.get()+"what?"#self.txt.get()
def closeEvent(self):
import tkMessageBox
if tkMessageBox.askokcancel("Quit", "Do you really wish to quit?"):
root.destroy()

if __name__ == '__main__':
root=tk.Tk()

a=App(root)
a.master.title("App Hello")
a.master.maxsize(1000, 400)
root.mainloop()

个人对Tk不熟,而Py的文档里重点在绑定的部分了。
不过想比与PyQt等更现代的Gui库来说,Tkinter使用起来更加简单一些。


test

《重构》里有一张说明了为什么要自动测试,另一种解释是测试驱动开发。
其实手工测试是很常见的事情,这里的区别是在是否自动上面,并获得如何的好处。
Py中模块有用 if __name__ == '__main__': 写测试兼示例的习惯。

Python中提供的若干开发工具,例如:
pydoc用于从源代码生成文档,文本来自__doc__部分。
doctest是基于文本的测试,匹配命令交互方式下的执行结果。
unittest的功能是自动单元测试,测试代码由TestCase类型派生,并添加给TestSuite。
test模块提供回归测试,用于在代码就该后执行之前的全部或部分测试代码。


thread

通常使用threading模块,而较低层的是thread。
所以简单的做法便是派生threading.Thread(或者直接创建并指定target属性)并重写run方法,
并使用若干synchronization对象。

other


还可以写python内部的机制,比如import或者parse什么的。


----
说明一下,上文只是简单列举语言对接口的实现。
重点不在语言上面也不在接口上面,而建立起的一份整体印象。
不过全篇看来也没列到什么特别的东西,都算是基础性的吧。

没有评论: