posts - 18,  comments - 19,  trackbacks - 0

应用程序国际化,在开源世界里常以i18n被提及,i18n是Internationalization的简写,正好18个字母。在wxPython程序进行i18n,如果字符串是编码在源文件中时,完全可按照python程序的i18n的方法,即使用gexttext和locale模块。而wxPython程序在使用XRC文件做为界面资源时,则应使用wx.Locale模块,它封装了区域化相关的操作。i18n,或者国际化实际上涉及到语言习惯,数字格式等等类别的内容。这里只介绍语言多国化,将一个简单的英文程序转换为中文,涉及到源文件,可从这里下载。

创建PO文件

PO文件是Portable Object文件的简称,它包含需要翻译的字符串。我们需要从源文件进行提取。首先,对源文件test.py编辑,标识代码里需要翻译的字符串内容。我们使用_("xx")的方法,这种形式可能在许多开源源代码中见识过。

#加载菜单栏
menubar = rc.LoadMenuBar('IDR_MENU')

这里的IDR_MENU是资源标识ID,不需要翻译,因此不做改变,而下面的代码:

info.SetVersion('1.0')
info.SetDescription('XRC i18n Demo')

'XRC i18n Demo'是描述性的文本,需要进行翻译,将需要处理为

info.SetVersion('1.0')
info.SetDescription(_('XRC i18n Demo'))

接着需要生成.pot(Portable Object Template),这是po的模板文件。在将来程序可能配置成其他语种,其他语言的po文件都从它而来。为了创建这文件,需要用到GNU gettext工具集中的xgettext。向xgettext传入些必要的信息,来创建.pot文件。

>xgetttext --output=test.pot test.py

我们将wxPython界面以XRC文件保存了,那里同样有要翻译的字符串需要提取。用XRCed工具将XRC生成python代码,勾选上'Generate gettext strings'项即可。将源文件和XRC生成的test_xrc.py文件一起处理,生成一个test.pot。

>xgettext --output=test.pot test.py test_xrc.py

将得到的test.pot另存为test.po文件,然后进行翻译编辑,在这过程中文件需要使用utf-8编码。将对应的英文翻译成中文,将charset更改为utf-8。

"Content-Type: text/plain; charset=utf-8\n"
"Content-Transfer-Encoding: 8bit\n"

#: test.py:19
msgid "XRC i18n Demo"
msgstr "XRC 国际化示例"
...

.pot和.po这些文件都是文本文件,主要供翻译者使用。为了使程序在运行时能获取相关的翻译的内容,要进行所谓的编译过程,将文本文件转换为二进制文件.mo。这里用了gettext工具集中的另一程序msgfmt。

> msgfmt --output=test.mo test.po

因为windows下没有像linux像有公共存储.mo文件的目录,保持平台的迁移性,在应用程序本地目录下新建locale目录,用来存放编译过的.mo文件,然后将test.mo移动至locale目录。在完成这些步骤后,就转入代码方面的更改了。

wxPython代码更改

原先的代码只需要做小改动:

def OnInit(self):
    wx.Locale.AddCatalogLookupPathPrefix('locale')
    self.locale = wx.Locale(wx.LANGUAGE_CHINESE_SIMPLIFIED)
    self.locale.AddCatalog('test')
    import __builtin__
    __builtin__.__dict__['_'] = wx.GetTranslation

首先,增加了新的目录文件路径,这将使wxPython搜索这个目录,寻找匹配的.mo文件。接着创建wx.Locale对象,将其初始化为简体中文,这将对应于zh_CN。最后将wx.GetTranslation做了一全局映射,这样你在其他类中,比如示例中TestFrame也能使用_('xx')调用。这样wxPython的i18n工作就完成了,下面是翻译前后的界面截图。

wxpython

一些有益的讨论

.mo文件的查找目录

如果你将locale目录下的test.mo文件删除掉,然后将test.py中的wx.LANGUAGE_CHINESE_SIMPLIFIED改为wx.LANGUAGE_CHINESE,重新运行程序看看。发现界面变成了如下的繁体中文,但是菜单'档案'下的Exit还是英文。

wxzh

因为缺失.mo文件,但又指定wx.LANGUAGE_CHINESE,wxPython运行时使用了wxstd.mo文件。wxstd.mo有许多预编译好的常见字符串的对应关系,它随wxPython发布,在wx/locale下有许多语言版本的wxstd.mo。

对于wxPython会对待查目录"DIR"来搜索.mo文件,查找它下面的这些目录,(DIR/LANG/LC_MESSAGES;DIR/LANG;DIR),对于哪些是待查目录,各个系统下又有不同,在所有的平台上,LC_PATH环境变量指定的目录将成为待查目录,在Linux下/share/locale, /usr/share/locale, /usr/lib/locale, /usr/locale /share/locale以及当前目录将是待查目录。在上面我们已经用过AddCatalogLookupPathPrefix()函数,其作用就是增加自己的待查目录。

在示例程序中,将test.mo放在locale\zh_CN\LC_MESSAGES或者locale\zh\LC_MESSAGES同样是可行的。但是如果使用wx.LANGUAGE_CHINESE指定,则zh_CN目录将不可行,因为它只是特化目录,指简体中文,而zh目录同样适用。

工具链再讨论

gettext进行国际化是开源社区的主流方案,它也提供了许多实用工具供使用。上面提到了xgettext,msgfmt,还有msginit.exe,它将根据.pot文件创建新的.po文件,然后初始化一些元信息,像作者信息,项目,以及编码等,当然也可像上面的手工编辑。msgmerge.exe将两个.po文件进行合并。除了使用GNU Gettext工具集,也可使用随python发布的tool\i18n目录下pygettext.py和msgfmt.py,它们等同于上述的两个工具。

对于编辑.po文件,可以尝试一下Poedit,它提供了图形化的编辑环境,其他功能我就不清楚了。

posted @ 2008-07-15 20:21 len 阅读(16) | 评论 (0)编辑 收藏

在Windows下,许多网络程序的连接依赖于IE浏览器中的代理服务器的设置,IE浏览器的代理设置很可能设定了注册表中的全局网络连接配置。

我在IE浏览器中设置了代理,而使用Maxthon浏览网页。在写Python时,用了urllib2库,后来出现了下面的错误:

urllib2.URLError: <urlopen error (10061, 'Connection refused')>

先前这个程序是运行正确的,又直接用浏览器访问需要的网址,正常。通过排查,发现IE浏览器中设置了代理,而代理无效,而urllib2库使用其网络配置,因此无法连接。通过取消代理,程序连接正常。

还有一例是,刚才用Windows Live Writer检索日志,和发布日志时出错,分别显示如下的错误:

error err

这也是因为WLW使用IE的网络设置,造成的网络错误而显示的错误提示。

因此在设置了IE代理,并使用其他与网络相关的程序,要特别注意其是否对IE代理设置有依赖。像Maxthon等就可选择不使用IE代理配置的选项。

posted @ 2008-07-08 13:27 len 阅读(19) | 评论 (0)编辑 收藏

Windows Live Writer是写博客的利器,非常好用。只是对一些常见的html标签支持不足,比如没有预排文本标签<pre>之类的。在插入示例代码时,我不喜欢使用网上的那些高亮插件,它们增加了一些我感觉不友好的标签元素。我在写文章时,代码放在<pre>标签,然后使用自定义的code类,如果是一些屏幕输入输入文本,会用一个console类来进行说明。如果直接从源代码拷贝文本至html源文件时,xml文件的的<>"之类标签需要进行转义才可以。在这之前,我都需要手工将WLW切换到HTML模式进行创作,然后修改这些标签,非常麻烦。这样干了几次后,昨天决定自己写个WLW插件用。在搜索引擎的帮助下,找到Dflying Chen的 为Windows Live Writer开发插件——InsertSearchPageLink这篇文章,并在其参照完成了插件编写。

但在找到这篇文章之前,和编写插件的过程中,还是费了很多功夫。最早我认为写插件是需要下载SDK之类的软件,所以在Live Writer官方开发网站,Live Writer网,MSDN之类的找了个遍,看见是有SDK之类字样的下载,但弄不下来只有文档,根本不见其什么头文件,DLL之类的。在这花费了很多时间,最后才发现WLW插件的SDK是随WLW一起分发了,也就是WindowsLive.Writer.Api.dll之类的,这些dll 都随WLW主程序在一个目录中。还有一点是,现在WLW在中国是随Live套件一起发布的,因此路径由原来的C:\Program Files\Windows Live Writer变成了C:\Program Files\Windows Live\Writer,插件目录为Plugin。如果在网上发现有好用的插件,只需要将其发布的插件dll扔到这个目录就行了。

在开发中碰到图标资源不能成功加载,在Dflying Chen的文章中特意提到了图标资源需要是嵌入形式,我也按照其操作的,总以为是这里出现问题。后来花了一些时间,才找到总是的根源:自己在开发中更改了工程名,导致最后生成的程序集的名称与后来的命名空间名称不一致,图标路径就出错了。C#也只是这次用一下,这些都没有接触到。

昨天弄完自己的“插入Pre标记”插件后,想到自己写博客常需要截图,遂想再开发一个截图工具的。最早搜到了别人调用SnagIt搜件,不好用,因为SnagIt是商业软件,需要注册的。后来找到了picpick,小巧免费,非常实用。我想调用picpick的,但是在参照Insert SnagIt Screen Capture发现是用COM接口,而无奈picpick没有这样供开发使用的接口考虑,最终不可行。后来经过一些其他的尝试,都告失败。最后还是搜索帮了忙,找到了Screen Capture这个插件,原来有别人已完工了。

最后附上,我用这个新插件截的图,非常好用,只需一步:

tmp196

posted @ 2008-07-05 21:43 len 阅读(70) | 评论 (0)编辑 收藏

安装Cygwin

cgywin官方主页下载安装文件setup.exe,这只是一个网络安装包,体积很小。cgywin包含了许多GNU下的应用程序,真正安装时会根据你选择的组件,会自动去网上下载安装的。在国内最好使用镜像服务,这样速度会提高很多,建议去http://www.cygwin.net.cn/http://www.cygwin.cn/下载上述的安装包,并在安装进行到Choose A Download Site这个步骤时,选择合理的镜像。由于中国南北网速的差异,上述两个地址都尝试一下,看看哪个对你而言速度更快一些。

在进行到Select Packages这个步骤时,选择你需要包,建议如下:

  • Shells -> rxvt-unicode-x  强大的X终端,可用它替换windows下的cmd.exe
  • Net-> openssh  ssh客户端,可作putty的替换
  • Net-> inetutils  可选,包含一些基本的网络工具,如telnet,否则在cygwin下无法使用windows的telnet

cygwin安装时会自动进行包关联,在安装rxvt时,已自动将X server安装上了。

配置调整

启动cygwin,实际上是运行cgywin.bat批处理,它又调用了cmd.exe。我们将安装的rxvt作为默认终端,需要修改cygwin.bat。下面是我机子上的配置修改,请对应修改相应的路径。

@echo off
d:
chdir d:\Cygwin\bin
rxvt -e bash --login -i

调整rxvt观感,需要修改你用户主目录下的.Xdefaults文件,此文件在你选择的安装目录下的home\usrname下,在我的机子上是D:\Cgywin\home\len。若不存在,可在此目录下新建一个,修改内容如下:

Rxvt*background:        black
Rxvt*foreground:        #E2E6C7 
Rxvt*font:              9x16 
Rxvt*boldFont:          9x16 
Rxvt*scrollBar_right:   True
Rxvt*saveLines:         1024
Rxvt*geometry:          80x30
Rxvt*color0:            black
Rxvt*color1:            red
Rxvt*color2:            green   
Rxvt*color3:            yellow
Rxvt*color4:            blue
Rxvt*color5:            magenta
Rxvt*color6:            cyan    
Rxvt*color7:            white   
Rxvt*color8:            burlywood1
Rxvt*color9:            sienna1 
Rxvt*color10:           PaleVioletRed1  
Rxvt*color11:           LightSkyBlue    
Rxvt*color12:           white   
Rxvt*color13:           white
Rxvt*color14:           white   
Rxvt*color15:           white 

在cygwin下也是可以访问Windows下其他盘符的,如cd /cygdrive/c/windows,就转到了C盘windows目录下。这样对于在linux下工作的人说有点儿别扭,更希望是以cd /mnt/c/windows的mount方式来访问其他盘符。这需要修改注册表的选项,将HKLM\software\Cygnus Solutions\Cgywin\mounts v2下的子项cygdrive prefix更改为/mnt即可。

远程登陆Linux桌面

其实这里介绍的不仅仅适用于Linux,而是针对X Window的。X Widonw的介绍不进行赘述,但需要明确其中的服务器端和客户端的区别,在X Window的概念中服务器端是指你进行显示,输入输出的机器,也是接下来示例中的本机len-computer,IP为10.3.164.70,而客户端指的是进行远程登陆的机器auto-desktop,IP为10.3.164.74。

在局域网内最简单的方法是使用XDMCP连接,这时远程的机器启用xdmcp。那台机器运行着ubuntu-8.04,用gdm进行窗口管理,编辑/etc/gdm/gdm.conf-custom如下,其他版本的linux需找到对应的窗口管理的配置文件。

[security]
DisallowTCP=false

[xdmcp]
Enale=true

修改完后,在远程机器上重启服务,$sudo /etc/init.d/gdm restart。接下来本机启动cgywin,转到X目录下,运行Xwin.exe,使用 -query指定远程的linux机器的ip即可。

Len@len-computer /usr/X11R6/bin
$ cd /usr/X11R6/bin

Len@len-computer /usr/X11R6/bin
$ Xwin -query 10.3.164.74

这里会出现如下面图示的窗口,提示输入用户名和密码。另再附一张在登陆成功后,我在本地执行远程操作的截图。

login

cygwinX

如果你需要连接的远程机器比较固定,可以修改本地机器d:\cgygin\usrX11R6\bin\startxdmcp.bat中的REMOTE_HOST值为你需要连接机器的IP,这个批处理设置了一些有用的环境变量值。或许你需要创建一个桌面的快键方式,这样每次点击,就直接连接到远程机器了。

不引入桌面环境

可能有时候只需要将某个需要X服务的远程应用程序引入到本地桌面显示,而不需要启动像上面的GNOME或者KDE等庞大的桌面环境。这样做比较适合喜欢终端操作的人,我就常常终端敲命令,然后将gvim,openoffice这些从远程导入到本地操作。

找到d:\cgywin\usr\X11R6\bin\startwin.bat,将%RUN% xterm -e /usr/bin/bash -l注释掉,因为我们己经有了rxvt,不需要一个新的xterm终端了,执行该批处理文件,就会在本机运行X server。启动cgywin,用ssh登陆到远程机器上,执行如下命令,导出DISPLAY环境变量和运行你感兴趣的程序。

auto@Auto-desktop:~$ export DISPLAY=10.3.164.70:0.0
auto@Auto-desktop:~$ gvim&
[1] 22652
auto@Auto-desktop:~$ oowriter&

其中环境变量DISPLAY中的:0.0部分表示X server的display和screen。display指运行着X server实例。如果使用TCP/IP连接,表示的是端口6000+display号做为连接。screen代表X server上的不同输出设备。我在例子中执行gvim和openoffice.org-writer,运行的效果可看下面的截图。在ubuntu上运行着的gvim和openoffice都在我本机10.3.164.70上显示了,并且可操作。

screen

有用的链接

Cgywin/X FAQ 在碰到一些操作问题时,不妨先看看这份FAQ

使用cygwin X server实现Linux远程桌面 easwy介绍了KDE环境下的配置,部分受此启发

使用rxvt做为cygwin终端 碰到rxvt中文显示问题时,或许有帮助

posted @ 2008-07-03 21:55 len 阅读(50) | 评论 (0)编辑 收藏

QQ在许多公司内部被禁止使用,为了能使用QQ,稍微懂点儿计算机的人都知道用代理。QQ提供了socket和http代理这两种功能,socket代理功能强大,但一般公司对外允许连接的端口号比较有限,难以利用。大多数公司是允许连接外部的80端口的,这样使用QQ的http代理是可行的。但是找到能用的QQ代理有点儿麻烦,因此下面的Python代码提供了自动进行QQ代理验证的功能。

import urllib2
import socket
import re

f = urllib2.urlopen('http://www.proxycn.com/html_proxy/http-1.html')
content = f.read()
f.close()
ipPattern = re.compile(r'(\d+\.\d+\.\d+\.\d+):80')
ipList = ipPattern.findall(content)
print ipList
requestData = "CONNECT http.tencent.com:443 HTTP/1.1\x0d\x0a"
requestData += "Accept: */*\x0d\x0aContent-Type: text/html\x0d\x0a"
requestData += "Proxy-Connection: Keep-Alive\x0d\x0a"
requestData += "Content-length: 0\x0d\x0a\x0d\x0a"
for ip in ipList:

    s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    try:
        s.connect((ip,80))
        s.send(requestData)
        data = s.recv(64)
        if data.find("200 Connection established")!= -1:
            print ip, 'good'
            # A vailable proxy is found once, then exit the program
            s.close
            exit(0)
        else:
            print ip, 'bad'
    except socket.error:
        print ip, 'dead'
    finally:
        s.close

程序在找到一个可用的QQ代理后退出,用good标识。另两种代理服务器的状态是dead,说明本地无法连接到代理服务器,或是bad,能与代理服务器建立连接,但是代理不能与QQ服务器通讯。

代码思路

通过代理中国获取到80端口的代理服务器列表,使用了urllib2模块获取页面数据,然后正则表达式解析出80端口的IP地址存入list中。接下来的几行代码简单,但是很重要,使用较为底层的socket对象,构造合适的数据包通过代理,请求与QQ服务器连接,通过读取的返回数据包来验证连接是否能建立。

这里主要涉及到了HTTP协议的CONNECT的概念,很多人可能认为http代理只是为web浏览提供服务,其实CONNECT方法允许允许用户建立TCP连接到任何端口,这意味着代理不仅可用于HTTP,还可用于FTP,QQ等其他协议。只是网上提供CONNECT方法的代理服务器比较少,我有时候扫了一大堆,也没有找到一个可用的代理。反过来说,有时候你找到的能浏览网页的http服务器,未必能用在QQ上,QQ需要的是能CONNECT的代理。网页浏览一般只使用HTTP协议的GET或POST方法,提供这两种方法的服务器就多了。

了解了代码的原理,稍做改动,就可以用于其他类型的代理的验证了,需要的是一些基本网络知识和数据报的发送和接收。

posted @ 2008-07-02 22:13 len 阅读(35) | 评论 (0)编辑 收藏

Subversion的属性是非常好用的功能,它将一些工作自动化,实现为受版本控制的源文件添加元信息的作用。属性是外部不可见的,可以简单认为是附加上在文件上的信息,和文件大小之类的信息是一样的,只不过他是通过subversion来管理的。属性的名称和值可以是你希望的任何值,限制就是名称必须是可读的文本,并且最好的一点是这些属性也是版本化的,就像你的文本文件内容,你可以像提交文本修改一样修改、提交和恢复属性修改,当你更新时也会接收到别人的属性修改—你不必为适应属性改变你的工作流程。

Subversion保留了一组名称以svn:开头的属性,来预定义一些有用的功能。比如你常会看到一些人的源代码底部有像下面之类标识的文字:

$Id: main_window.py 68 2008-06-30 02:05:05Z Len $

这就使用了Subversion 中的 svn:keywords的自动属性,它让将发生在源代码中的一些属性的变化自动地更新到源代码中。这行字的意思是表示,main_windows.py 这个源代码文件最后被用户 len 更新于 2008-6-30 02:05:05Z,修订版本号为 68。要实现这样的自动更新,你只要对需要这样属性的文件上使用下面这行指令。

> svn propset svn:keywords "Id" main_window.py

或者使用TortoiseSVN中的Properties的操作按钮,方便地增加新的属性。接着需要在源代码文件中需要 Subversion 进行自动更新的地方插入 $Id$ 这样的 Keyword,那么在你下次进行提交更新时,该$Id$ 就会被 Subversion 自动替换为$Id: main_window.py 68 2008-06-30 02:05:05Z Len $ 这样的格式。
Subversion 中可以使用的Keyword 包括下面这些:

  • Id
    上面介绍过的综合的格式
  • LastChangedDate
    最后被修改的时间,缩写为 Date。
  • LastChangedBy
    最后修改该源代码文件的用户名,缩写为 Author。
  • LastChangedRevision
    最后修订的版本号,缩写为 Revision。

如果想每次向Subversion服务器提交文件修改时,都要设置文件的属性,则需要进行Subversion配置的修改。配置文件在你用户的主目录下,在Windows下应类似于C:\Documents and Settings\Len\Application Data\Subversion\config文件,Len是Windows用户名,注意Application Data是隐藏文件夹,需要显示全部文件才能看到。接着如下相应的修改,对你想要处理的文件做配置。

enable-auto-props = yes   
[auto-props]   
*.c = svn:keywords=Id   
*.py = svn:keywords=Id 

对于开源项目,常见其源文件头部有着版权声明的文本,这些操作大多也是通Subversion的属性功能来完成的,有关更详细的介绍和操作指南,可参见Subversion中文手册中的属性章节。

posted @ 2008-06-30 12:06 len 阅读(31) | 评论 (0)编辑 收藏

这个类表示在单独的控制线程中运行的活动。有两种方法可以指定这种活动,给构造函数传递回调对象,或者在子类中重写run() 方法。其他方法(除了构造函数)都不应在子类中被重写。换句话说,在子类中只有__init__()run()方法被重写。

一旦线程对象被创建,它的活动需要通过调用线程的start()方法来启动。这方法再调用控制线程中的run方法。

一旦线程被激活,则这线程被认为是'alive'(活动)。当它的run()方法终止时-正常退出或抛出未处理的异常,则活动状态停止。isAlive()方法测试线程是否是活动的。

一个线程能调用别的线程的join()方法。这将阻塞调用线程,直到拥有join()方法的线程的调用终止。

线程有名字。名字能传给构造函数,通过setName()方法设置,用getName()方法获取。

线程能被标识为'daemon thread'(守护线程).这标志的特点是当剩下的全是守护线程时,则Python程序退出。它的初始值继承于创建线程。这标志用setDaemon()方法设置,用isDaemon()获取。

存在'main thread'(主线程),它对应于Python程序的初始控制线程。它不是后台线程。

有可能存在'dummy thread objects'(哑线程对象)被创建。这些线程对应于'alien threads'(外部线程),它们在Python的线程模型之外被启动,像直接从C语言代码中启动。哑线程对象只有有限的功能,它们总是被认为是活动的,守护线程,不能使用join()方法。它们从不能被删除,既然它无法监测到外部线程的中止。

class Thread(group=None, target=None, name=None, args=(), kwargs={})

构造函数能带有关键字参数被调用。这些参数是:

group 应当为 None,为将来实现ThreadGroup类的扩展而保留。

target 是被 run()方法调用的回调对象. 默认应为None, 意味着没有对象被调用。

name 为线程名字。默认,形式为'Thread-N'的唯一的名字被创建,其中N 是比较小的十进制数。

args是目标调用参数的tuple,默认为()。

kwargs是目标调用的参数的关键字dictionary,默认为{}。

如果子线程重写了构造函数,它应保证调用基类的构造函数(Thread.__init__()),在线程中进行其他工作之前。

start()
启动线程活动。

在每个线程对象中最多被调用一次。它安排对象的run() 被调用在一单独的控制线程中。

run()

用以表示线程活动的方法。

你可能在子类重写这方法。标准的 run()方法调用作为target传递给对象构造函数的回调对象。如果存在参数,一系列关键字参数从argskwargs参数相应地起作用。

join([timeout])
等待至线程中止。这阻塞调用线程直至线程的join() 方法被调用中止-正常退出或者抛出未处理的异常-或者是可选的超时发生。

timeout参数未被设置或者不是None,它应当是浮点数指明以秒计的操作超时值。因为join()总是返回None,你必须调用isAlive()来判别超时是否发生。

timeout 参数没有被指定或者是None时,操作将被阻塞直至线程中止。

线程能被join()许多次。

线程不能调用自身的join(),因为这将会引起死锁。

在线程启动之前尝试调用join()会发生错误。

getName()
返回线程名。
setName(name)
设置线程名。

这名字是只用来进行标识目的的字符串。它没有其他作用。多个线程可以取同一名字。最初的名字通过构造函数设置。

isAlive()
返回线程是否活动的。

大致上,线程从 start()调用开始那点至它的run()方法中止返回时,都被认为是活动的。模块函数enumerate()返回活动线程的列表。

isDaemon()
返回线程的守护线程标志。
setDaemon(daemonic)
设置守护线程标志为布尔值daemonic。它必须在start()调用之前被调用。

初始值继承至创建线程。

当没有活动的非守护线程时,整个Python程序退出。

参见:Python Library Reference

posted @ 2008-06-24 16:54 len 阅读(39) | 评论 (0)编辑 收藏

介绍

cURL是一个利用URL语法的文件传输工具,是基于libcurl的前端命令行工具。它支持很多协议:FTP, FTPS, HTTP, HTTPS, GOPHER, TELNET, DICT, FILE 以及 LDAP。 它同样支持HTTPS认证,HTTP POST方法, HTTP PUT方法, FTP上传, kerberos认证, HTTP上传, 代理服务器, cookies, 用户名/密码认证, 下载文件断点续传, 上载文件断点续传, http代理服务器管道( proxy tunneling), 甚至它还支持IPv6, socks5代理服务器,通过http代理服务器上传文件到FTP服务器等等,功能十分强大。

除了使用curl命令行直接进行相关的网络操作,你也可以自由地使用libcurl,它是用C语言编写的,可以绑定到众多的编程语言中,如C,C++,PHP,Python,Perl,Java等等。你可以很方便地利用libcurl,在程序中进行一些网络传输工作,来代替一些语言的内置,使你的知识可重用。在Unix工作环境下,你可以用curl代替wget和ftp等工具,并能将这种学习经验迁移到将来使用libcurl来完成一些自动化任务。

curl是瑞典curl组织开发的,可以通过http://curl.haxx.se/来获取更详细的信息和下载文件。

curl命令行工具使用

curl太强大了,只能对其HTTP的部分作一简单的介绍,其他选项可以参见其附带的手册。它的后端库的使用也非常方便,主要也是在选项设置上,跟命令行基本无异。

用法

curl [选项] [URL...]

URL 语法

URL语法是跟协议相关的,具体细节可参见RFC 3986
可以指定多个URLs或者部分URL地址,通过花括号{}进行分割:
http://site.{one,two,three}.com
或者用[]使用字母序:
ftp://ftp.numericals.com/file[1-100].txt
ftp://ftp.numericals.com/file[001-100].txt (有前导零)
ftp://ftp.letters.com/file[a-z]].txt

当前序列嵌套不被支持,但是还是可以使用下列的样式:
http://any.org/archive[1996-1999]/vol[1-4]/part{a,b,c}.html
可以在命令行指定任意数量的URLs,它们将以指定的顺序被取回。

从curl7.15.1开始指定可以范围步长,所以可以得到第n个数或字母:
http://www.numericals.com/file[1-100:10].txt
http://www.letters.com/file[a-z:2].txt

如果使用了protocal://前缀,curl会将尝试你想使用的协议。它默认使用HTTP,但是其他一些协议也常被用作主机名。比如说,以"ftp"打头的主机名,curl会假定你想使用ftp协议。

Curl会尝试对多文件传输使用重连接,可以使从同一服务器获取很多文件时,不会进行多次的连接。这种做法改进了速度,当然这只会在同一命令行中指定的文件启用,而不会在独立的Curl调用时使用。

进度指示器

curl通常在操作时会显示一个进度指示器,来指明当前的传输量,传输速度和预计的剩余时间等等。

但是,即然curl默认将数据显示在终端,如果你调用curl进行操作,它会将数据打印到终端上,这时它会禁用掉进度指示器,否则这些会将输出信息搞乱掉。

如果在进行HTTP的POST或PUT请求时,你想将输出重定向到文件中,可以使用shell的重定向符(>),或者类似的-o[file]选项。

但是在FTP上传并不会这样,这些操作不会将数据插入到终端中。

如果想使用进度栏,而不是常规的指示器,那么-#会非常有帮助。

常用的HTTP选项

-A/--user-agent<agent string>
(HTTP)指定用户代理字符串发送给HTTP服务器。如果这个字段没有被设为"Mozilla/4.0",某些CGIs将不会正常工作。如果在字符串中存在空白字符,需要用单引号标识。这个字段值也可用-H/--header选项进行设置。
如果这选项被多次设置,最后的设置将起作用。

-b/--cookie<name=data>
(HTTP)将data作为cookie传给HTTP服务器,这数据当然是在使用了"Set-Cookie:"后,先前从服务端接收到的。这数据应是"NAME1=VALUE1;NAME2=VALUE2"的格式。
如果没有"="字符,它将会当作先前存储cookie行的文件名,如果它能被匹配的话。使用这选项,也能激活"cookie parser",它使curl记录传入的cookies数据。将它与-L/--locaion选项组合将会更加便利。被读取cookie的文件格式应当是文本HTTP头或者Netscape/Mozilla cookie文件格式。
注意:被-b/--cookie指定的文件只能作为输入使用。没有cookie会存储在这文件中。为了存储cookie,应使用-c/--cookie-jar选项或者直接将HTTP头输出到文件中,用-D/--dump-header选项。这选项可以设置多次,但是只有最后一个起作用。

-connect-timeout<seconds>
以秒计的最大超时,用于进行服务器连接时。这只在连接阶段起作用,一旦curl连接建立,这选项将不再起作用。

-c/--cookie-jar<file name>
指定在完成一系列操作后,需要将全部的cookie信息保存到哪个文件中。Curl会将先前读取的cookie的信息和从服务器返回的信息一起保存。如果没有cookie信息,则不会进行写文件。cookie信息的文件将与Netscape cookie文件格式保存。如果文件名被设置为'-',则将cookie打印至终端。
注意:如果cookie-jar不能被创建写入,整个curl操作也不会失改,甚至不会向你报告错误.使用-v将会得到警告显示,但也只能在可能导致发生致命错误的情况才会显示。

--create-dirs
这与-o选项配合使用,curl会在需要时建立本地文件夹结构。这选项会创建在-o选项中涉及到的文件夹。如果-o选项中的文件名没有使用到文件夹,或者所需的文件夹已经存在,则不会有文件夹创建。

-D/--dump-header<file>
将协议头写到指定的文件中。当你想存储HTTP站点发给你的数据时,这选项非常有用。在协议头中的cookie将来可以用curl的另外调用来进行读取,那就是-b/--cookie选项。但是-c/--cookie-jar选项将会是更好的存储cookie信息的方法。
当使用FTP协议时,ftp服务器的应答信息将相应地当作成协议头,然后被存储。

-p/-proxytunnel
当HTTP代理被设置后(-x/--proxy),选项会使不是HTTP协议的传输试图通过代理隧道,而不是表现得HTTP类似的操作形为。代理隧道的方法是通过HTTP服务器直接使用CONNECT请求,让代理直接连接到curl隧道所请求的远程端口号的方式来实现的。

-o/--output<file>
将输出信息打印到文件中,而不是终端。可使用{}或者[]取回多个文档,可在file指定格式中的'#'跟一数字,这样这变量将会由取回的URL字符串所取代。如下:
curl http://{one,two}.site.com -o "file_#1.txt"
如果有多个变量,可以写成下面的样子:
curl http://{site.host}.host[1-5].com -o "#1_#2"
你可对任意数量的URL使用同样多的这个选项

-x/--proxy<proxyhost[:port]>
使用指定的HTTP代理,如果端口号没有被指定,默认为1080.
这选项会覆盖环境变量中代理服务器的设置。如果环境变量中设置了代理,可将proxy设置为空字符串,来覆盖环境变量中的设置。
注意:所有通过HTTP代理的操作都会自动转化为HTTP协议。这意味着一些特定协议的操作将会变得无效。这不会有问题,如果在设置了-p/--proxytunnel选项来通过代理隧道进行操作。

简单示例

获取cppblog首页,打印至终端

>curl http://www.cppblog.com
重定向,保存到文件cppblog.html
>curl http://www.cppblog.com
作用同上,使用选项
>curl -o baidu.html http://www.baidu.com
使用http代理,可指定IP和端口
>curl -x 202.127.98.43:80 -o baidu.html http:www.baidu.com
在访问一些论坛时,常常要求启用cookie,因为这些网站需要启用cookie来记录sessioin信息,这时需要选项-D,将cookie信息保存起来
>curl -o cpp.html -c len@cppblog.com[1].txt http://www.cppblog.com

先前保存的cookie信息返回给网站,这通常会传回你的一些用户信息。
>curl -o cpp.html -c len@cppblog.com[2].txt -b len@cppblog.com[1].txt http://www.cppblog.com
posted @ 2008-06-21 16:33 len 阅读(172) | 评论 (0)编辑 收藏

介绍

命令行接口是普遍,基础的人机交互接口,从命令行提取程序的运行时选项的方法有很多。你可以自己编写相对应的完整的解析函数,或许你有丰富的C语言编程经验,熟知getopt()函数的用法,又或许使用Python的你已经在使用optparse库来简化这一工作。大家在平时不断地谈及到“不要重复造轮子”,那就需要掌握一些顺手的库,这里介绍一种C++方式来解析命令行选项的方法,就是使用Boost.Program_options库。

program_options提供程序员一种方便的命令行和配置文件进行程序选项设置的方法。使用program_options库而不是你自己动手写相关的解析代码,因为它更简单,声明程序选项的语法简洁,并且库自身也非常小。将选项值转换为适合的类型值的工作也都能自动完成。库有着完备的错误检查机制,如果自己手写解析代码时,就可能会错过对一些出错情况的检查了。最后,选项值不仅能从命令行获取,也能从配置文件,甚至于环境变量中提取,而这些选择不会增加明显的工作量。

示例说明

以下面简单的hello程序进行说明,默认打印hello world,如果传入-p选项,就会打印出人的姓名,另外通过传入-h选项,可以打印出帮助选项。略微看一眼代码文件和相应的屏幕输入输出,然后我们再一起来看看这些是如何发生的。

//hello.cpp 
#include <iostream>
#include <string>
#include <boost/program_options.hpp>

using namespace std;
int main(int argc, char* argv[])
{
    using namespace boost::program_options;
    //声明需要的选项
    options_description desc("Allowed options");
    desc.add_options()
        ("help,h", "produce help message")
        ("person,p", value<string>()->default_value("world"), "who")
        ;

    variables_map vm;        
    store(parse_command_line(argc, argv, desc), vm);
    notify(vm);    

    if (vm.count("help")) {
        cout << desc;
        return 0;
    }
    cout << "Hello " << vm["person"].as<string>() << endl;
    return 0;
}

下面是在Windows命令提示符窗口上的输入输出结果,其中">"表示提示符。

>hello 
Hello world

>hello -h
Allowed options:
  -h [ --help ]                produce help message
  -p [ --person ] arg (=world) who

>hello --person len
Hello len

首先通过options_description类声明了需要的选项,add_options返回了定义了operator()的特殊的代理对象。这个调用看起来有点奇怪,其参数依次为选项名,选项值,以及选项的描述。注意到示例中的选项名为"help,h",是因为声明了具有短选项名和长选项名的选项,这跟gnu程序的命令行具有一致性。当然你可以省略短选项名,但是这样就不能用命令选项简写了。第二个选项的声明,定义了选项值为string类型,其默认值为world.

接下来,声明了variables_map类的对象,它主要用来存储选项值,并且能储存任意类型的值。然后,store,parse_command_line和notify函数使vm能存储在命令行中发现的选项。

最后我们就自由地使用这些选项了,variables_map类的使用就像使用std::map一样,除了它必须用as方法去获取值。如果as方法调用的指定类型与实际存储的类型不同,就会有异常抛出。

具有编程的你可能有这样的经验,使用cl或gcc对源文件进行编译时,可直接将源文件名放置在命令行中,而无需什么选项字母,如gcc a.c之类的。prgram_options也能处理这种情况,在库中被称为"positional options"(位置选项),但这需要程序员的一点儿帮助才能完成。看下面的经过对应修改的代码,我们无需传入"-p"选项,就能可指定"person"选项值

    positional_options_description p;
    p.add("person", -1);
    store(command_line_parser(argc, argv).options(desc).positional(p).run(), vm);
>hello len
Hello len

前面新增的两行是为了说明所有的位置选项都应被解释成"person"选项,这里还采用了command_line_parser类来解析命令行,而不是用parse_command_line函数。后者只是对前者类的简单封装,但是现在我们需要传入一些额外的信息,所以要使用类本身。

选项复合来源

一般来说,在命令行上指定所有选项,对用户来说是非常烦人的。如果有些选项要应用于每次运行,那该怎么办呢。我们当然希望能创建出带有些常用设置的选项文件,跟命令行一起应用于程序中。当然这一切需要将命令行与配置文件中的值结合起来。比如,在命令行中指定的某些选项值应该能覆盖配置文件中的对应值,或者将这些值组合起来。

下面的代码段将选项通过文件读取,这文件是文本格式,可用"#"表示注释,格式如命令行中的参数一样,选项=值

    ifstream ifs("config.cfg");
    store(parse_config_file(ifs,config),vm);
    notify(vm);

参考

Boost.prgram_options库文档

posted @ 2008-06-15 21:03 len 阅读(1032) | 评论 (0)编辑 收藏

涉及到软件:Xmanager 1.3.9 / Windows xp, ubuntu hardy

第一步,在ubuntu机器上配置好gdm,修改/etc/gdm/gdm.conf-custom,对照添加如下内容:

[security]
DisallowTCP=false
[xdmcp]
Enable=true

第二步,性能调优。这步非常关键,不然使用Xmanager登陆速度非常慢,且会报错,主要原因是gnome使用Esound进行声音数据的传送,需要使用TCP 16001端口。所以我建设在ubuntu关掉混音选项。
系统-首选项-音效-音效,将“允许软件混音”不要勾选上,
系统-首选项-字体-字体渲染,选择"单色",在“细节”的“字体渲染细节”中的平滑和微调选项,都选择"无"。

有用的参考:http://www.netsarang.com/products/xmg_faq.html

posted @ 2008-06-01 21:10 len 阅读(92) | 评论 (0)编辑 收藏
仅列出标题  下一页

<2008年7月>
293012345
6789101112
13141516171819
20212223242526
272829303112
3456789

常用链接

留言簿(1)

随笔分类

随笔档案

搜索

  •  

最新评论

  • 1. re: 可爱的Vim
  • @路过
    汗自己,不是不小心,是英语不行,自以为是了
  • --len
  • 2. re: 可爱的Vim
  • @路过
    支持
  • --不懂
  • 3. re: 可爱的Vim
  • lz一定不小心打错了 ultraedit 不是 Utraledit
    改软件不能处理二进制 ... 写代码提示功能不如相应的编辑工具
    没事儿玩玩的路过...

  • --路过
  • 4. re: 可爱的Vim
  • 评论内容较长,点击标题查看
  • --len
  • 5. re: 可爱的Vim
  • @爱好编程
    windows下一样可以用,呵呵,用得也非常好
    我就是在windows下用
  • --len

阅读排行榜

评论排行榜