nginx使用三方模块方法

nginx文件非常小但是性能非常的高效,这方面完胜apache,nginx文件小的一个原因之一是nginx自带的功能相对较少,好在nginx允许第三方模块,第三方模块使得nginx越发的强大. 在安装模块方面,nginx显得没有apache安装模块方便,当然也没有php安装扩展方便.在原生的nginx,他不可以动态加载模块,所以当你安装第三方模块的时候需要覆盖nginx文件.接下来看看如何安装nginx第三模块吧.

nginx第三方模块安装方法:
[codesyntax lang=”text”]

./configure --prefix=/你的安装目录  --add-module=/第三方模块目录

[/codesyntax]
以安装pagespeed模块实例

在未安装nginx的情况下安装nginx第三方模块
[codesyntax lang=”text”]

# ./configure --prefix=/usr/local/nginx-1.4.1 \
--with-http_stub_status_module \
--with-http_ssl_module --with-http_realip_module \
--with-http_image_filter_module \
--add-module=../ngx_pagespeed-master --add-module=/第三方模块目录
# make
# make isntall
# /usr/local/nginx-1.4.1/sbin/nginx

[/codesyntax]

在已安装nginx情况下安装nginx模块
[codesyntax lang=”text”]

# ./configure --prefix=/usr/local/nginx-1.4.1 \
 --with-http_stub_status_module \
 --with-http_ssl_module --with-http_realip_module \
 --with-http_image_filter_module \
 --add-module=../ngx_pagespeed-master
# make
# /usr/local/nginx-1.4.1/sbin/nginx -s stop
# cp objs/nginx /usr/local/nginx/sbin/nginx
# /usr/local/nginx-1.4.1/sbin/nginx

[/codesyntax]

相比之下仅仅多了一步覆盖nginx文件.

总结,安装nginx安装第三方模块实际上是使用–add-module重新安装一次nginx,不要make install而是直接把编译目录下objs/nginx文件直接覆盖老的nginx文件.如果你需要安装多个nginx第三方模块,你只需要多指定几个相应的–add-module即可.

备注:
重新编译的时候,记得一定要把以前编译过的模块一同加到configure参数里面.

nginx提供了非常多的nginx第三方模块提供安装,地址http://wiki.nginx.org/3rdPartyModules

Django对数据库的封装——QuerySet

Django对数据库的操作分用到三个类:Manager、QuerySet、Model。Manager的主要功能定义表级方法(表级方法就是影响一条或多条记录的方法),我们可以以models.Manager为父类,定义自己的manager,增加表级方法;QuerySet是Manager的方法返回的,是一个可遍历结构,包含一个或多个元素,每个元素都是一个Model 实例,它里面的方法也是表级方法,前面说了,Django给我们提供了增加表级方法的途径,那就是自定义manager类,而不是自定义QuerySet类,一般的我们没有自定义QuerySet类的必要;Model是一条记录的类,它的功能很强大,里面包含外键实体等,它的方法都是记录级方法(都是实例方法,无类方法),不要在里面定义类方法,比如计算记录的总数,查看所有记录,这些应该放在自定义的manager类中。

1.QuerySet

1.1 简介

每个Model都有一个默认的manager类,名为objects,QuerySet有两种来源:通过manager的方法得到、通过QuerySet的方法得到。QuerySet的最初来源就是通过manager的方法。mananger的方法和QuerySet的方法大部分同名,同意思,如filter(),update()等,但也有些不同,如manager有create()、get_or_create(),而QuerySet有delete()等。一个QuerySet包含一个或多个model instance。QuerySet类似于Python中的list,list的一些方法QuerySet也有,比如切片,遍历。

>>> from gk_user.models import UserEx
>>> type(UserEx.objects)
<class 'django.db.models.manager.Manager'>
>>> a = UserEx.objects.all()
>>> type(a)
<class 'django.db.models.query.QuerySet'>

QuerySet是延迟获取的,只有当用到这个QuerySet时(有下面几种情况),才会求值,即查询数据库。另外,查询到的QuerySet又是缓存的,当再次使用同一个QuerySet时,并不会再查询数据库,而是直接从缓存获取(不过,有一些特殊情况)。一般而言,当对一个没有求值的QuerySet进行的运算返回的不是QuerySet、ValuesQuerySet、ValuesListQuerySet、Model实例时,一般的会立即查询数据库;反之,运算返回的是QuerySet、ValuesQuerySet、ValuesListQuerySet、Model实例时,一般不会查询数据库。下面介绍几种(并非全部)对QuerySet求值的场景。

class Blog(models.Model):
    name = models.CharField(max_length=100)
    tagline = models.TextField()
def __unicode__(self):
    return self.name
     
class Author(models.Model):
    name = models.CharField(max_length=50)
    email = models.EmailField()
def __unicode__(self):
    return self.name
    
class Entry(models.Model):
    blog = models.ForeignKey(Blog)
    headline = models.CharField(max_length=255)
    body_text = models.TextField()
    pub_date = models.DateField()
    mod_date = models.DateField()
    authors = models.ManyToManyField(Author)
    n_comments = models.IntegerField()
    n_pingbacks = models.IntegerField()
    rating = models.IntegerField()
def __unicode__(self):
    return self.headline

我们以上面的models为例。

I 遍历

a = Entry.objects.all()
for e in a:
    print (e.headline)

当遍历时,先从数据库执行查询select * from Entry得到a,然后再遍历a。注意:这里只是查询Entry表,返回的a的每条记录只包含Entry表的字段值。不管Entry的model中是否有onetoone、onetomany、manytomany字段,都不会关联查询。这遵循的是数据库最少读写原则。我们修改一下代码,如下,遍历一开始也是先执行查询得到a,但当执行print (e.blog.name)时,还需要再次查询数据库获取blog实体。

from django.db import connection

l = connection.queries #l是一个列表,记录SQL语句

a = Entry.objects.all()

for e in a:

print (e.blog.name)

len(l)

遍历时,每次都要查询数据库,l长度每次增1,Django提供了方法可以在查询时返回关联表实体,如果是onetoone或onetomany,那用select_related,不过对于onetomany,只能在主表(定义onetomany关系的那个表)的manager中使用select_related方法,即通过select_related获取的关联对象是model instance,而不能是QuerySet,如下,e.blog就是model instance。对于onetomany的反向和manytomany,要用prefetch_related,它返回的关联对象是QuerySet。

a = Entry.objects.select_related(‘blog’)

for e in a:

print (e.blog.name)

len(l)

可以看到从开始到结束,l的长度只增加1。另外,通过查询connection.queries[-1]可以看到Sql语句用了join。

II 切片

切片不会立即执行,除非显示指定了步长,如a= Entry.objects.all()[0:10:2],步长为2。

III 序列化,即Pickling

序列化QuerySet很少用

IV repr()

和str()功能相似,将对象转为字符串,很少用。

V len()

计算QuerySet元素的数量,并不推荐使用len(),除非QuerySet是求过值的(即evaluated),否则,用QuerySet.count()获取元素数量,这个效率要高。

VI list()

将QuerySet转为list

VII bool() ,判断是否为空

if Entry.objects.filter(headline="Test"):
    print("There is at least one Entry with the headline Test")

同样不建议这种方法判断是否为空,而应该使用QuerySet.exists(),查询效率高

1.2 QuerySet的方法

数据库的常用操作就四种:增、删、改、查,QuerySet的方法涉及删、改、查。后面还会讲model对象的方法,model方法主要是增、删、改、还有调用model实例的字段。

(1) 删delete()

原型:delete()

返回:None

相当于delete-from-where, delete-from-join-where。先filter,然后对得到的QuerySet执行delete()方法就行了,它会同时删除关联它的那些记录,比如我删除记录表1中的A记录,表2中的B记录中有A的外键,那同时也会删除B记录,那ManyToMany关系呢?不清楚。实际中,delete用的很少,对于没有用的记录,一般是update为不可用。由于有些数据库,如Sqlite不支持delete与limit连用,所以在这些数据库对QuerySet的切片执行delete()会出错。如

>>> a = UserEx.objects.filter(is_active=False)
>>> b = a[:3]
>>> b.delete() #执行时会报错

解决:UserEx.objects.filter(pk__in=b).delete()

in后面可以是一个QuerySet,见 https://docs.djangoproject.com/en/1.6/ref/models/querysets/#in

(2) 改 update()

批量修改,返回修改的记录数。不过update()中的键值对的键只能是主表中的字段,不能是关联表字段,如下:

Entry.objects.update(blog__name='foo') #这是错误的,无法修改关联表字段,只能修改Entry
#表中的字段
Entry.objects.filter(blog__name='foo').update(comments_on=False) #正确,filter中的字段可以
#是关联表

最好的方法是先filter,查询出QuerySet,然后再执行QuerySet.update()。

由于有些数据库,不支持update与limit连用,所以在这些数据库对QuerySet的切片执行update()会出错。

(3)查询 filter(**kwargs)、exclude(**kwargs)、get(**kwargs)

相当于select-from-where,select-from-join-where,很多网站读数据库操作最多。可以看到,filter()的参数是变个数的键值对,而不会出现>,<,!=等符号,这些符号分别用__gt,__lt,~Q或exclude(),不过对于!=,建议使用Q查询,更不容易出错。可以使用双下划线对OneToOne、OneToMany、ManyToMany进行关联查询和反向关联查询,而且方法都是一样的,如:

>>> Entry.objects.filter(blog__name='Beatles Blog') 
#限定外键表的字段下面是反向连接,不过要注意,这里不是entry_set,
#entry_set是Blog 实例的一个属性,代表某个Blog对象的关联的所有entry,
#而QuerySet的方法中反向连接是直接用model的小写,不要把两者搞混。
#反过来也是一样,如果想根据现有对象找原对象,将原类型对象小写即可。
>>> Blog.objects.filter(entry__headline__contains='Lennon')
>>> Blog.objects.filter(entry__authors__name='Lennon') #ManyToMany关系,反向连接
>>> myblog = Blog.objects.get(id=1)
>>> Entry.objects.filter(blog=myblog) 
#正向连接。与下面一句等价,既可以用实体,也可以用实体的主键。
#其实即使用实体,也是只用实体的主键而已。这两种方式对OneToOne、
#OneToMany、ManyToMany的正向、反向连接都适用。
>>> Entry.objects.filter(blog=1)
>>> myentry = Entry.objects.get(id=1)
>>> Blog.objects.filter(entry=myentry) #ManyToMany反向连接。与下面一句等价
>>> Blog.objects.filter(entry=1)

OneToOne的关系也是这样关联查询,可以看到,Django对OneToOne、OneToMany、ManyToMany关联查询及其反向关联查询提供了相同的方式,真是牛逼啊。对于OneToOne、OneToMany的主表,也可以使用下面的方式

Entry.objects.filter(blog_id=1),因为blog_id是数据库表Entry的一个字段, 这条语句与Entry.objects.filter(blog=1)生成的SQL是完全相同的,都是只在Entry表查询,没用join,django为我们封装了对数据库的操作,所以建议只用model中的字段,而blog_id不是model定义的字段,不建议用。

与filter类似的还有exclude(**kwargs)方法,这个方法是剔除,相当于select-from-where not,select-from-join-where not。可以使用双下划线对OneToOne、OneToMany、ManyToMany进行关联查询和反向关联查询,方法与filter()中的使用方法相同。

>>> Entry.objects.exclude(pub_date__gt=datetime.date(2005, 1, 3), headline=’Hello’)

转为SQL为

SELECT *
FROM Entry
WHERE NOT (pub_date > '2005-1-3' AND headline = 'Hello')

HTTPD启动绑定端口失败

问题描述:

在apache中绑定非http标准端口时,一直出现如下的错误提示:

[root@localhost ~]# /etc/init.d/httpd start
Starting httpd: (13)Permission denied: make_sock: could not bind to address 0.0.0.0:8087
no listening sockets available, shutting down
Unable to open logs

原因分析:

该问题是由SELinux 引起的

解决方案:

 

1、快速解决,修改selinux级别(不推荐)

vi /etc/sysconfig/selinux 
SELINUX=enforcing =>SELINUX=disabled 
reboot

 

2、从根本上解决(推荐)

根据自己的需求在selinux中添加需要指定的端口
前提需要先安装semanage(Centos6.0默认没有安装该应用)
a)安装方式如下:

[root@localhost /]# yum provides /usr/sbin/semanage
[root@localhost /]# yum whatprovides /usr/sbin/semanage
[root@localhost /]# yum -y install policycoreutils-python
[root@localhost /]# semanage

b)使用semanage添加apache侦听的端口

查看现在的支持http的端口有哪些

[root@localhost /]# semanage port -l|grep http 
为http服务添加新的端81 

[root@localhost /]# semanage port -a -t http_port_t -p tcp 81 
查看添加的结果 

[root@localhost /]# semanage port -l|grep http

 

DB2 IMPORT 详解

IMPORT 实用程序概述

IMPORT 实用程序用一个输入文件将数据填充到一个表中,输入文件的文件类型可以是 ASC、DEL、IXF 或 WSF。目标是一个表、一个类型化表(typed table)或者一个视图。但是,不能导入到系统表、临时表和物化查询表。建议使用 MESSAGES 子句,以便记录错误、警告和包含有用信息的消息。

要想成功地导入数据,必须拥有 SYSADM 或 DBADM 权限,或者目标表或数据库上的底层特权(SELECT、INSERT、CONTROL 或 CREATETAB),这取决于使用什么选项。为了将数据导入到一个包含受保护的行和列的表中,必须拥有允许对表中所有受保护数据进行写访问的 LBAC 凭证。此外,将数据导入包含受保护行的表时,要求您的 LBAC 凭证是保护表的安全策略的一部分。

下面显示的 IMPORT 命令具有五个不同的选项:

[codesyntax lang=”sql”]

IMPORT FROM file_name OF file_type
   MESSAGES message_file
   [ INSERT | INSERT_UPDATE | REPLACE | REPLACE_CREATE | CREATE ]
   INTO target_table_name
   

[/codesyntax]

INSERT 选项将导入的数据插入表中。目标表必须已经存在。 INSERT_UPDATE 将数据插入表中,或者更新表中具有匹配主键的行。目标表必须已经存在,并且定义了一个主键。 REPLACE 选项删除所有已有的数据,并将导入的数据插入到一个已有的目标表中。 使用 REPLACE_CREATE 选项时,如果目标表已经存在,则导入实用程序删除已有的数据,并插入新的数据,就像 REPLACE 选项那样。如果目标表还没有定义,那么首先创建这个表以及它的相关索引,然后再导入数据。正如您可能想像的那样,输入文件必须是 PC/IXF 格式的文件,因为那种格式包含对导出表的结构化描述。如果目标表是被一个外键引用的一个父表,那么就不能使用 REPLACE_CREATE。 CREATE 选项首先创建目标表和它的索引,然后将数据导入到新表中。该选项惟一支持的文件格式是 PC/IXF。还可以指定新表所在表空间的名称。 例子:

[codesyntax lang=”sql”]

IMPORT FROM emp.ixf OF IXF
   MESSAGES msg.out
   CREATE INTO employee IN datatbsp INDEX IN indtbsp

[/codesyntax]

IMPORT 选项

IMPORT 基本上是用于成批插入数据的一个实用程序。这种成批插入操作就像一般的插入语句一样,也涉及到活动的日志记录、索引的更新、参照完整性检查和表约束检查。默认情况下,IMPORT 只在操作结束时提交一次。如果将大量的行一次性导入或插入到表中,那么需要有足够的事务记录用于回滚和恢复。此外也可以采用周期性的提交,以防日志写满。通过定期地提交插入,还可以减少导入操作期间出现失败时丢失的行数。COMMITCOUNT 选项规定在导入一组记录后强制执行 COMMIT。还可以指定 AUTOMATIC 选项,该选项允许导入实用程序在内部决定何时需要执行提交。该实用程序将考虑发出一个提交命令,以避免日志写满或者避免锁升级。下面是关于如何使用 COMMITCOUNT 选项的一个例子:

[codesyntax lang=”sql”]

IMPORT FROM myfile.ixf OF IXF
   COMMITCOUNT 500
   MESSAGES msg.out
   INSERT INTO newtable
   

[/codesyntax]

如果由于某种原因导致以上命令在执行期间遭到失败,那么可以使用消息文件来确定成功导入且已提交的最后一行。然后,可以使用 RESTARTCOUNT 选项重新开始导入。注意,SKIPCOUNT 选项的行为与 RESTARTCOUNT 是相同的。在下面的命令中,该实用程序在开始 IMPORT 操作之前,将忽略前 30,000 条记录。

[codesyntax lang=”sql”]

IMPORT FROM myfile.ixf OF IXF
   COMMITCOUNT 500 RESTARTCOUNT 30000 ROWCOUNT 100000
   MESSAGES msg.out
   INSERT INTO newtable

[/codesyntax]

注意,这个例子中还使用了 ROWCOUNT 选项。该选项指定要导入的物理记录的条数。由于使用了 RESTARTCOUNT 选项,导入实用程序将忽略前 30,000 条记录,并且将剩下的 100,000 条记录导入到表中。

默认情况下,在插入任何行之前,导入实用程序将获得目标表上的一个排它锁。一旦导入完成,这个排它锁将被释放。这是 ALLOW NO ACCESS 选项的行为。为了允许并发应用程序访问表数据,可以使用 ALLOW WRITE ACCESS 选项。注意,该选项与 REPLACE、CREATE 或 REPLACE_CREATE 导入选项不兼容。下面是关于 ALLOW WRITE ACCESS 选项的一个例子。

[codesyntax lang=”sql”]

IMPORT FROM myfile.ixf OF IXF
   ALLOW WRITE ACCESS
   MESSAGES msg.out
   INSERT INTO newtable

[/codesyntax]

导入 XML 数据

为了导入 XML 文件,可以使用 XML FROM 选项指定 XML 文件所在的一个或多个路径。否则,导入实用程序将在当前目录中查找 XML 文件。您可以选择如何解析 XML 文档;是去掉空白还是保留空白。如果没有指定 XMLPARSE 选项,那么将根据 CURRENT XMLPARSE OPTION 专用寄存器来决定对 XML 文档的解析行为。下面是关于 XML FROM 和 XMLPARSE 选项的一个例子。

[codesyntax lang=”sql”]

IMPORT FROM myfile.ixf OF IXF
   XML FROM d:\xmlpath
   XMLPARSE PRESERVE WHITESPACE
   MESSAGES msg.out
   INSERT INTO newtable
   

[/codesyntax]

当插入或更新一个 XML 文档时,您可能想确定 XML 文档的结构、内容和数据类型是否有效。导入实用程序还通过 XMLVALIDATE 选项提供了对 XML 验证的支持。下面是可用的三种方法。

USING XDS — 回想一下,您可以导出 XML 模式信息并将它存储在 XML Data Specifier (XDS) 的 SCH 属性中。SCH 属性的值将用于执行验证。如果在 XDS 中没有 SCH 属性,则考虑 DEFAULT、IGNORE 或 MAP 三者之中的一个值。 USING SCHEMA schema-sqlid — 使用这个子句中指定的 XML 模式。 USING SCHEMALOCATION HINTS — 根据源 XML 文档中 XML 模式位置提示所标识的模式来验证 XML 文档。

[codesyntax lang=”sql”]

IMPORT FROM myfile.ixf OF IXF
   XML FROM d:\xmlpath
   XMLPARSE PRESERVE WHITESPACE
   XMLVALIDATE USING XDS
   DEFAULT S1.SCHEMA_A
   IGNORE (S1.SCHEMA_X, S1.SCHEMA_Y, S1.SCHEMA_Z)
   MAP (S1.SCHEMA_A, S1.SCHEMA_B)
   COMMITCOUNT 500 RESTARTCOUNT 30000
   MESSAGES msg.out
   INSERT INTO newtable
   

[/codesyntax]

前面的 IMPORT 命令将:

插入 myfile.ixf 和 d:\xmlpath 下的 XML 文件中的数据。 当解析 XML 文档时,保留空白。 使用 XDS 的 SCH 属性标识的模式信息对每个 XML 文档进行验证。但是,如果用于任何特定行的 XDS 没有包含 SCH 属性,那么使用 S1.SCHEMA_A。 如果 SCH 属性被指定为 S1.SCHEMA_X 或 S1.SCHEMA_Y 或 S1.SCHEMA_Z,那么对于导入的 XML 文档不执行验证。 如果 SCH 属性被指定为 S1.SCHEMA_A,它将被映射到 S1.SCHEMA_B。注意,尽管 DEFAULT 子句指定了 S1.SCHEMA_A,但是后面的任何映射都将不会执行。 每导入 500 行之后,导入实用程序将发出一次提交命令。 导入操作从第 30,001 条记录开始。前 30,000 条记录被忽略。 任何错误、警告和包含信息的消息都写到 msg.out 文件中。 将新数据插入(或附加)到 newtable 中。 这个例子只是让您对如何验证导入的 XML 文档有一些认识。DB2 Information Center 中还有更多的例子来演示 XMLVALIDATE 选项的威力。

文件类型修饰符

IMPORT 实用程序还支持五种文件类型修饰符来定制导入操作。在 DB2 Command Reference 的 IMPORT 小节下有这些修饰符的一个完整的列表。下面列出了其中一些修饰符:

compound=x 使用非原子复合 SQL 插入数据。x 是每次将尝试的语句数量。 indexschema=schema 使用索引创建期间指定的用于索引的模式。 striptblanks 将数据装载到可变长度字段时,截去结尾空白。 lobsinfile 表明将导入 LOB 数据。导入实用程序将检查 LOBS FROM 子句,以获得输入 LOB 文件的路径。

下面是使用这些文件类型修饰符的一个例子:

[codesyntax lang=”sql”]

IMPORT FOR inputfile.asc OF ASC
   LOBS FROM /u/db2load/lob1, /u/db2load/lob2
   MODIFIED BY compount=5 lobinsfile
   INSERT INTO newtable
   

[/codesyntax]

使用 Control Center 执行导入

Control Center 提供了易于使用的图形界面来执行导入操作。这个界面中还提供了前一屏中讨论的所有导入选项和文件修饰符。

Git rebase 详解

1.出现情况的背景:

当你提交的代码后,管理员发现,您的代码不能提交到服务器上,主要原因在于,你的commit 中和服务器中的有些commit不再同一时间轴上,即:你的有些commit要插入到服务器中的某些commit之间,这样就会造成代码的冲突。所以这个时候就要使用git rebase。

假如,你平时使用的分支叫new ,然后在这个分支上你刚提交过几个commit。

做法:

1.新建一个分支,并且代码和服务器中代码同步

[codesyntax lang=”text”]


git checkout origin/v2.0 -b temp

[/codesyntax]

2.为了保证新建的temp分支代码是最新的,可以多执行下面一步

[codesyntax lang=”text”]


git pull

[/codesyntax]

3.当你新建分支后,系统会自动checkout到temp分支上,此时

[codesyntax lang=”text”]


git checkout new

[/codesyntax]

4.合并代码,并整理

[codesyntax lang=”text”]


git rebase temp //会将temp分支的代码合并过来,并按照提交的顺序排序

[/codesyntax]

5. 因为顺序是重新整理的,所以肯定会出现冲突

6.解决冲突,最后git add * ,但不许要git commit

7.解决后,执行

[codesyntax lang=”text”]


git rebase --continue

[/codesyntax]

8.重新提交代码

[codesyntax lang=”text”]


git push for-*

[/codesyntax]

注意:如果要对某些代码的commit重新整理

1. 可以记住某个commit号

2. git rebase -i commit号

3. 会显示一个整理提交的界面,有很多参数,e。p。等等

4.将前面的参数改为e。则wq保存后,系统会自动让你重新修改commit内容

5.修改完成后,再git push for-*

python urllib2 详解

urllib2是Python的一个获取URLs(Uniform Resource Locators)的组件。他以urlopen函数的形式提供了一个非常简单的接口,
这是具有利用不同协议获取URLs的能力,他同样提供了一个比较复杂的接口来处理一般情况,例如:基础验证,cookies,代理和其他。
它们通过handlers和openers的对象提供。
urllib2支持获取不同格式的URLs(在URL的”:”前定义的字串,例如:”ftp”是”ftp:python.ort/”的前缀),它们利用它们相关网络协议(例如FTP,HTTP)
进行获取。这篇教程关注最广泛的应用–HTTP。
对于简单的应用,urlopen是非常容易使用的。但当你在打开HTTP的URLs时遇到错误或异常,你将需要一些超文本传输协议(HTTP)的理解。
最权威的HTTP文档当然是RFC 2616(http://rfc.net/rfc2616.html)。这是一个技术文档,所以并不易于阅读。这篇HOWTO教程的目的是展现如何使用urllib2,
并提供足够的HTTP细节来帮助你理解。他并不是urllib2的文档说明,而是起一个辅助作用。
获取 URLs
最简单的使用urllib2将如下所示
[codesyntax lang=”python”]

import urllib2 
response = urllib2.urlopen('http://python.org/') 
html = response.read()

[/codesyntax]
urllib2的很多应用就是那么简单(记住,除了”http:”,URL同样可以使用”ftp:”,”file:”等等来替代)。但这篇文章是教授HTTP的更复杂的应用。
HTTP是基于请求和应答机制的–客户端提出请求,服务端提供应答。urllib2用一个Request对象来映射你提出的HTTP请求,在它最简单的使用形式中你将用你要请求的
地址创建一个Request对象,通过调用urlopen并传入Request对象,将返回一个相关请求response对象,这个应答对象如同一个文件对象,所以你可以在Response中调用.read()。
[python]
import urllib2
req = urllib2.Request(‘http://www.voidspace.org.uk’)
response = urllib2.urlopen(req)
the_page = response.read()

[/codesyntax]
记得urllib2使用相同的接口处理所有的URL头。例如你可以像下面那样创建一个ftp请求。
req = urllib2.Request(‘ftp://example.com/’)
在HTTP请求时,允许你做额外的两件事。首先是你能够发送data表单数据,其次你能够传送额外的关于数据或发送本身的信息(“metadata”)到服务器,此数据作为HTTP的”headers”来发送。
接下来让我们看看这些如何发送的吧。
Data数据
有时候你希望发送一些数据到URL(通常URL与CGI[通用网关接口]脚本,或其他WEB应用程序挂接)。在HTTP中,这个经常使用熟知的POST请求发送。这个通常在你提交一个HTML表单时由你的浏览器来做。
并不是所有的POSTs都来源于表单,你能够使用POST提交任意的数据到你自己的程序。一般的HTML表单,data需要编码成标准形式。然后做为data参数传到Request对象。编码工作使用urllib的函数而非
urllib2。
[codesyntax lang=”python”]

import urllib 
import urllib2 
url = 'http://www.someserver.com/cgi-bin/register.cgi' 
values = {'name' : 'Michael Foord', 
          'location' : 'Northampton', 
          'language' : 'Python' } 
data = urllib.urlencode(values) 
req = urllib2.Request(url, data) 
response = urllib2.urlopen(req) 
the_page = response.read()

[/codesyntax]
记住有时需要别的编码(例如从HTML上传文件–看http://www.w3.org/TR/REC-html40/interact/forms.html#h-17.13 HTML Specification, Form Submission的详细说明)。
如ugoni没有传送data参数,urllib2使用GET方式的请求。GET和POST请求的不同之处是POST请求通常有”副作用”,它们会由于某种途径改变系统状态(例如提交成堆垃圾到你的门口)。
尽管HTTP标准说的很清楚POSTs通常会产生副作用,GET请求不会产生副作用,但没有什么可以阻止GET请求产生副作用,同样POST请求也可能不产生副作用。Data同样可以通过在Get请求
的URL本身上面编码来传送。
可看如下例子
[python:nogutter]
>>> import urllib2
>>> import urllib
>>> data = {}
>>> data[‘name’] = ‘Somebody Here’
>>> data[‘location’] = ‘Northampton’
>>> data[‘language’] = ‘Python’
>>> url_values = urllib.urlencode(data)
>>> print url_values
name=Somebody+Here&language=Python&location=Northampton
>>> url = ‘http://www.example.com/example.cgi’
>>> full_url = url + ‘?’ + url_values
>>> data = urllib2.open(full_url)

[/codesyntax]
Headers
我们将在这里讨论特定的HTTP头,来说明怎样添加headers到你的HTTP请求。
有一些站点不喜欢被程序(非人为访问)访问,或者发送不同版本的内容到不同的浏览器。默认的urllib2把自己作为“Python-urllib/x.y”(x和y是Python主版本和次版本号,例如Python-urllib/2.5),
这个身份可能会让站点迷惑,或者干脆不工作。浏览器确认自己身份是通过User-Agent头,当你创建了一个请求对象,你可以给他一个包含头数据的字典。下面的例子发送跟上面一样的内容,但把自身
模拟成Internet Explorer。
[codesyntax lang=”python”]

import urllib 
import urllib2 
url = 'http://www.someserver.com/cgi-bin/register.cgi' 
user_agent = 'Mozilla/4.0 (compatible; MSIE 5.5; Windows NT)' 
values = {'name' : 'Michael Foord', 
          'location' : 'Northampton', 
          'language' : 'Python' } 
headers = { 'User-Agent' : user_agent } 
data = urllib.urlencode(values) 
req = urllib2.Request(url, data, headers) 
response = urllib2.urlopen(req) 
the_page = response.read()

[/codesyntax]
response应答对象同样有两个很有用的方法。看下面的节info and geturl,我们将看到当发生错误时会发生什么。
Handle Exceptions处理异常
当urlopen不能够处理一个response时,产生urlError(不过通常的Python APIs异常如ValueError,TypeError等也会同时产生)。
HTTPError是urlError的子类,通常在特定HTTP URLs中产生。
URLError
通常,URLError在没有网络连接(没有路由到特定服务器),或者服务器不存在的情况下产生。这种情况下,异常同样会带有”reason”属性,它是一个tuple,包含了一个错误号和一个错误信息。
例如
[codesyntax lang=”python”]

>>> req = urllib2.Request('http://www.pretend_server.org') 
>>> try: urllib2.urlopen(req) 
>>> except URLError, e: 
>>>    print e.reason 
>>> 
(4, 'getaddrinfo failed')

[/codesyntax]
HTTPError
服务器上每一个HTTP 应答对象response包含一个数字”状态码”。有时状态码指出服务器无法完成请求。默认的处理器会为你处理一部分这种应答(例如:假如response是一个”重定向”,需要客户端从别的地址获取文档
,urllib2将为你处理)。其他不能处理的,urlopen会产生一个HTTPError。典型的错误包含”404″(页面无法找到),”403″(请求禁止),和”401″(带验证请求)。
请看RFC 2616 第十节有所有的HTTP错误码
HTTPError实例产生后会有一个整型’code’属性,是服务器发送的相关错误号。
Error Codes错误码
因为默认的处理器处理了重定向(300以外号码),并且100-299范围的号码指示成功,所以你只能看到400-599的错误号码。
BaseHTTPServer.BaseHTTPRequestHandler.response是一个很有用的应答号码字典,显示了RFC 2616使用的所有的应答号。这里为了方便重新展示该字典。(译者略)
当一个错误号产生后,服务器返回一个HTTP错误号,和一个错误页面。你可以使用HTTPError实例作为页面返回的应答对象response。这表示和错误属性一样,它同样包含了read,geturl,和info方法。
[codesyntax lang=”python”]

>>> req = urllib2.Request('http://www.python.org/fish.html') 
>>> try: 
>>>     urllib2.urlopen(req) 
>>> except URLError, e: 
>>>     print e.code 
>>>     print e.read() 
>>> 
404 

Error 404: File Not Found 
...... etc...

[/codesyntax]
Wrapping it Up包装
所以如果你想为HTTPError或URLError做准备,将有两个基本的办法。我则比较喜欢第二种。
第一个:
[codesyntax lang=”python”]

from urllib2 import Request, urlopen, URLError, HTTPError 
req = Request(someurl) 
try: 
    response = urlopen(req) 
except HTTPError, e: 
    print 'The server couldn/'t fulfill the request.' 
    print 'Error code: ', e.code 
except URLError, e: 
    print 'We failed to reach a server.' 
    print 'Reason: ', e.reason 
else: 
    # everything is fine

[/codesyntax]
注意:except HTTPError 必须在第一个,否则except URLError将同样接受到HTTPError。
第二个:
[codesyntax lang=”python”]

from urllib2 import Request, urlopen, URLError 
req = Request(someurl) 
try: 
    response = urlopen(req) 
except URLError, e: 
    if hasattr(e, 'reason'): 
        print 'We failed to reach a server.' 
        print 'Reason: ', e.reason 
    elif hasattr(e, 'code'): 
        print 'The server couldn/'t fulfill the request.' 
        print 'Error code: ', e.code 
else: 
    # everything is fine

[/codesyntax]
info and geturl
urlopen返回的应答对象response(或者HTTPError实例)有两个很有用的方法info()和geturl()
geturl — 这个返回获取的真实的URL,这个很有用,因为urlopen(或者opener对象使用的)或许
会有重定向。获取的URL或许跟请求URL不同。
info — 这个返回对象的字典对象,该字典描述了获取的页面情况。通常是服务器发送的特定头headers。目前是httplib.HTTPMessage 实例。
经典的headers包含”Content-length”,”Content-type”,和其他。查看Quick Reference to HTTP Headers(http://www.cs.tut.fi/~jkorpela/http.html)
获取有用的HTTP头列表,以及它们的解释意义。
Openers和Handlers
当你获取一个URL你使用一个opener(一个urllib2.OpenerDirector的实例,urllib2.OpenerDirector可能名字可能有点让人混淆。)正常情况下,我们
使用默认opener — 通过urlopen,但你能够创建个性的openers,Openers使用处理器handlers,所有的“繁重”工作由handlers处理。每个handlers知道
如何通过特定协议打开URLs,或者如何处理URL打开时的各个方面,例如HTTP重定向或者HTTP cookies。
如果你希望用特定处理器获取URLs你会想创建一个openers,例如获取一个能处理cookie的opener,或者获取一个不重定向的opener。
要创建一个 opener,实例化一个OpenerDirector,然后调用不断调用.add_handler(some_handler_instance).
同样,可以使用build_opener,这是一个更加方便的函数,用来创建opener对象,他只需要一次函数调用。
build_opener默认添加几个处理器,但提供快捷的方法来添加或更新默认处理器。
其他的处理器handlers你或许会希望处理代理,验证,和其他常用但有点特殊的情况。
install_opener 用来创建(全局)默认opener。这个表示调用urlopen将使用你安装的opener。
Opener对象有一个open方法,该方法可以像urlopen函数那样直接用来获取urls:通常不必调用install_opener,除了为了方便。
Basic Authentication 基本验证
为了展示创建和安装一个handler,我们将使用HTTPBasicAuthHandler,为了更加细节的描述本主题–包含一个基础验证的工作原理。
请看Basic Authentication Tutorial(http://www.voidspace.org.uk/python/articles/authentication.shtml)
当需要基础验证时,服务器发送一个header(401错误码) 请求验证。这个指定了scheme 和一个‘realm’,看起来像这样:Www-authenticate: SCHEME realm=”REALM”.
例如
Www-authenticate: Basic realm=”cPanel Users”
客户端必须使用新的请求,并在请求头里包含正确的姓名和密码。这是“基础验证”,为了简化这个过程,我们可以创建一个HTTPBasicAuthHandler的实例,并让opener使用这个
handler。
HTTPBasicAuthHandler使用一个密码管理的对象来处理URLs和realms来映射用户名和密码。如果你知道realm(从服务器发送来的头里)是什么,你就能使用HTTPPasswordMgr。
通常人们不关心realm是什么。那样的话,就能用方便的HTTPPasswordMgrWithDefaultRealm。这个将在你为URL指定一个默认的用户名和密码。这将在你为特定realm提供一个其他组合时
得到提供。我们通过给realm参数指定None提供给add_password来指示这种情况。
最高层次的URL是第一个要求验证的URL。你传给.add_password()更深层次的URLs将同样合适。
[codesyntax lang=”python”]

# 创建一个密码管理者 
password_mgr = urllib2.HTTPPasswordMgrWithDefaultRealm() 
# 添加用户名和密码 
# 如果知道 realm, 我们可以使用他代替 ``None``. 
top_level_url = "http://example.com/foo/" 
password_mgr.add_password(None, top_level_url, username, password) 
handler = urllib2.HTTPBasicAuthHandler(password_mgr) 
# 创建 "opener" (OpenerDirector 实例) 
opener = urllib2.build_opener(handler) 
# 使用 opener 获取一个URL 
opener.open(a_url) 
# 安装 opener. 
# 现在所有调用 urllib2.urlopen 将用我们的 opener.

[/codesyntax]
urllib2.install_opener(opener)
注意:以上的例子我们仅仅提供我们的HHTPBasicAuthHandler给build_opener。默认的openers有正常状况的handlers–ProxyHandler,UnknownHandler,HTTPHandler,HTTPDefaultErrorHandler, HTTPRedirectHandler, FTPHandler, FileHandler, HTTPErrorProcessor。
top_level_url 实际上可以是完整URL(包含”http:”,以及主机名及可选的端口号)例如:http://example.com/,也可以是一个“authority”(即主机名和可选的
包含端口号)例如:“example.com” or “example.com:8080”(后者包含了端口号)。权限验证,如果递交的话不能包含”用户信息”部分,例如:
“joe@password:example.com”是错误的。
Proxies代理urllib 将自动监测你的代理设置并使用他们。这个通过ProxyHandler这个在正常处理器链中的对象来处理。通常,那工作的很好。但有时不起作用
。其中一个方法便是安装我们自己的代理处理器ProxyHandler,并不定义代理。这个跟使用Basic Authentication 处理器很相似。
[codesyntax lang=”python”]

>>> proxy_support = urllib.request.ProxyHandler({}) 
>>> opener = urllib.request.build_opener(proxy_support) 
>>> urllib.request.install_opener(opener)

[/codesyntax]
注意:
此时urllib.request不支持通过代理获取https地址。但,这个可以通过扩展urllib.request达到目的。
Sockets and Layers
Python支持获取网络资源是分层结构。urllib 使用http.client库,再调用socket库实现。
在Python2.3你可以指定socket的等待回应超时时间。这个在需要获取网页的应用程序里很有用。默认的socket模型没有超时和挂起。现在,socket超时没有暴露 www.2cto.com
给http.client或者urllib.request层。但你可以给所有的sockets设置全局的超时。

Git 乱码处理方法

乱码情景1

在cygwin中,使用git add添加要提交的文件的时候,如果文件名是中文,会显示形如274\232\350\256\256\346\200\273\347\273\223.png的乱码。

解决方案:

在bash提示符下输入:

[codesyntax lang=”text”]

git config --global core.quotepath false

[/codesyntax]
core.quotepath设为false的话,就不会对0×80以上的字符进行quote。中文显示正常。

乱码情景2

在MsysGit中,使用git log显示提交的中文log乱码。

解决方案:

设置git gui的界面编码

[codesyntax lang=”text”]

git config --global gui.encoding utf-8

[/codesyntax]
设置 commit log 提交时使用 utf-8 编码,可避免服务器上乱码,同时与linux上的提交保持一致!

[codesyntax lang=”text”]

git config --global i18n.commitencoding utf-8

[/codesyntax]
使得在 $ git log 时将 utf-8 编码转换成 gbk 编码,解决Msys bash中git log 乱码。

[codesyntax lang=”text”]

git config --global i18n.logoutputencoding gbk

[/codesyntax]
使得 git log 可以正常显示中文(配合i18n.logoutputencoding = gbk),在 /etc/profile 中添加:

[codesyntax lang=”text”]

export LESSCHARSET=utf-8

[/codesyntax]

乱码情景3

在MsysGit自带的bash中,使用ls命令查看中文文件名乱码。cygwin没有这个问题。

解决方案:

使用?lls --show-control-chars?命令来强制使用控制台字符编码显示文件名,即可查看中文文件名。

为了方便使用,可以编辑?/etc/git-completion.bash?,新增一行?alias ls="ls --show-control-chars"

Linux查看系统资源情况

1. 查看CPU使用情况的命令

$ vmstat 5

每5秒刷新一次,最右侧有CPU的占用率的数据

$ top

top 然后按Shift+P,按照进程处理器占用率排序

2. 查看内存使用情况的命令

$ free

$ top

top 然后按Shift+M, 按照进程内存占用率排序

3. 查看网络流量

可以用工具iptraf工具

$ iptraf -g

“”针对某个Interface的网络流量可以通过比较两个时间网络接口的RX和TX数据来获得

$ date; ifconfig eth1

4. 查看磁盘i/o

$ iostat -d -x /dev/sdc3 2

用iostat查看磁盘/dev/sdc3的磁盘i/o情况,每两秒刷新一次

$ vmstat 2

用vmstat查看io部分的信息

procs:
r–>;在运行队列中等待的进程数
b–>;在等待io的进程数
w–>;可以进入运行队列但被替换的进程

memoy:
swap–>;现时可用的交换内存(k表示)
free–>;空闲的内存(k表示)

pages:
re--》回收的页面
mf--》非严重错误的页面
pi--》进入页面数(k表示)
po--》出页面数(k表示)
fr--》空余的页面数(k表示)
de--》提前读入的页面中的未命中数
sr--》通过时钟算法扫描的页面

disk 显示每秒的磁盘操作。 s表示scsi盘,0表示盘号

fault 显示每秒的中断数
in--》设备中断
sy--》系统中断
cy--》cpu交换

cpu 表示cpu的使用状态
cs--》用户进程使用的时间
sy--》系统进程使用的时间
id--》cpu空闲的时间

其中:
如果 r经常大于 4 ,且id经常少于40,表示cpu的负荷很重。
如果pi,po 长期不等于0,表示内存不足。
如果disk 经常不等于0, 且在 b中的队列 大于3, 表示 io性能不好。

Git ignore详解

环境

Windows XP SP3 + TortoiseGit + msysGit

 

ignore files的三种方法

以下涉及的ignore文件均为如下格式:

#?以’#’开始的行,被视为注释.#?忽略掉所有文件名是?foo.txt的文件.

foo.txt

#?忽略所有生成的?html文件,

*.html

# foo.html是手工维护的,所以例外.

!foo.html

#?忽略所有.o和?.a文件.

*.[oa]

 

【方式一】

在仓库目录下新建一个名为.gitignore的文件(因为是点开头,没有文件名,没办法直接在windows目录下直接创建,必须通过右键Git Bash,按照linux的方式来新建.gitignore文件)。如下图所示。

.gitignore文件对其所在的目录及所在目录的全部子目录均有效。通过将.gitignore文件添加到仓库,其他开发者更新该文件到本地仓库,以共享同一套忽略规则。

【方式二】

通过配置.git/info/exclude文件来忽略文件。这种方式对仓库全局有效,只能对自己本地仓库有作用,其他人没办法通过这种方式来共享忽略规则,除非他人也修改其本地仓库的该文件。

 

【方式三】

通过.git/config配置文件的core. Excludesfile选项,指定一个忽略规则文件(完整路径),如下图所示。忽略规则在文件e:/gitignore.txt中(当然该文件名可以任意取)。

该方式的作用域是也全局的。

 

【例子】

[codesyntax lang=”text”]
# 忽略*.o和*.a文件
?*.[oa]
# 忽略*.b和*.B文件,my.b除外
*.[bB]
!my.b
# 忽略dbg文件和dbg目录
dbg
# 只忽略dbg目录,不忽略dbg文件
dbg/
# 只忽略dbg文件,不忽略dbg目录
dbg
!dbg/
# 只忽略当前目录下的dbg文件和目录,子目录的dbg不在忽略范围内
/dbg
[/codesyntax]

解决Git pull出现non-fast-forward错误

当要push代码到git时,出现提示:

error:failed to push some refs to …

Dealing with “non-fast-forward” errors
From time to time you may encounter this error while pushing:

$ git push origin master
To ../remote/
! [rejected]        master -> master (non-fast forward)
error: failed to push some refs to ‘../remote/’

To prevent you from losing history, non-fast-forward updates were rejected
Merge the remote changes before pushing again.  See the ‘non-fast forward’
section of ‘git push –help’ for details.
This error can be a bit overwhelming at first, do not fear. Simply put, git cannot make the change on the remote without losing commits, so it refuses the push. Usually this is caused by another user pushing to the same branch. You can remedy this by fetching and merging the remote branch, or using pull to perform both at once.
In other cases this error is a result of destructive changes made locally by using commands like git commit –amend or git rebase. While you can override the remote by adding –force to the push command, you should only do so if you are absolutely certain this is what you want to do. Force-pushes can cause issues for other users that have fetched the remote branch, and is considered bad practice. When in doubt, don’t force-push.

 

问题(Non-fast-forward)的出现原因在于:git仓库中已经有一部分代码,所以它不允许你直接把你的代码覆盖上去。于是你有2个选择方式:

1,强推,即利用强覆盖方式用你本地的代码替代git仓库内的内容

git push -f

2,先把git的东西fetch到你本地然后merge后再push

$ git fetch

$ git merge

这2句命令等价于

  1. $ git pull

可是,这时候又出现了如下的问题:

上面出现的 [branch “master”]是需要明确(.git/config)如下的内容
[branch “master”]
remote = origin

merge = refs/heads/master

这等于告诉git2件事:

1,当你处于master branch, 默认的remote就是origin。

2,当你在master branch上使用git pull时,没有指定remote和branch,那么git就会采用默认的remote(也就是origin)来merge在master branch上所有的改变

如果不想或者不会编辑config文件的话,可以在bush上输入如下命令行:

$ git config branch.master.remote origin
$ git config branch.master.merge refs/heads/master

之后再重新git pull下。最后git push你的代码吧。it works now~