Sunday, November 29, 2009

使用urllib2抓网页数据

搞这种事, 主要是有时候需要脚本自动化地去处理一些烦锁的事. 至少不用狂copy, paste两个动作.(-_-), 有时也少量还行, 大量就浪费生命了.

HTTP的访问过程就是一来一回的. python提供的urllib2很方便发起访问请求:
 * urllib2.urlopen(url)
url为完整的URL
 * urllib2.urlopen(request)
request为urllib2.Request类实例

这样就发起了HTTP访问请求.

现在的网站一般都会对自动处理脚本起防范的. 比如在header段的cookie,  还有就是在post请求发出的数据中加入key=value形式的一串字符串.

I. 请求的header段处理
header在python对应的数据结构就是dict, 如:
{'cookie': '111111111111111', 'Accept-Encoding': 'gzip,deflate'}
使用方法:
request = urllib2.Request(url, headers) # headers就是字典实例
retval = urllib2.urlopen(request)  # 请求将被发出去

II. post的数据处理
post的数据在python对应的数据结构是str, 如:
'person=jessinio&gender=male'

使用方法有两种:
1.
retval = urllib2.urlopen(url='http://www.google.com', data='person=jessinio&gender=male') #这样一个post请求就被发出去了.

2.
request = urllib2.Request(url, data='person=jessinio&gender=male') #指定request实例拥有的data字符串
retval = urllib2.urlopen(request)  # 请求将被发出去

* 只要知道headers和post请求需要的数据结构是对应于python哪种实例后就很容易使用urllib2库

请求发出来, 接来又来一个问题: 请求后返回的数据是什么东西?

全世界都知道返回的东西肯定是字符流~~~(-_-)

常常在平时出现这样的问题: 请求一个html文件, 但返回的不是文本数据. 比如gzip. 那就需要处理一次:
    if retval.headers.has_key('content-encoding'):
        fileobj = StringIO.StringIO()
        fileobj.write(url.read())
        fileobj.seek(0)
        gzip_file = gzip.GzipFile(fileobj=fileobj)
        context = gzip_file.read()
    else:
        context = url.read()

这样就很方便得到文本数据了.










Wednesday, November 18, 2009

method和function在python一样吗?

之前学习了descriptor和decorator之后就感觉到python里的类方法中第一个参数: cls 有淫技的存在, 还没有时间理会它. 当然, 学习有不一定通的情况, 只是到刚刚能感觉到"淫"意的地步.

今天和朋友又聊到了self.

结果他妈的...... self不是keyword!! 我靠.... 还有这种事..... 自欺!! 人类的死点....

就是因为这样, 就把下面的事挖出来了.

自然提出一个问题: method与function是不是同一概念? 如下代码:

In [12]: class M(object):
   ....:     def func_or_method(self,name):
   ....:         print name
   ....:         
   ....:        
In [13]: M.func_or_method
Out[13]: <unbound method M.func_or_method>

In [14]: M.__dict__['fun_or_method']
Out[14]: <function func_or_method at 0x94e66f4>

同一个事物, 不同的调用方式, 产生了不同的结果. 不得不让人想到"淫技"一词.

这一切都是源于object和type的__getatrribute__. 因为它是一个hook. 偷天换日只有它能做到.

在: http://users.rcn.com/python/download/Descriptor.htm 里 Invoking Descriptors 一节中道出了__getattribute__的黑暗事实: 把对object和type的"."这种属性获取语法全换成了:
1. 对于object : type(b).__dict__['x'].__get__(b, type(b))
2. 对于type : B.__dict__['x'].__get__(None, B)

这部份转换工作是C实现的. 上面的python代码只是模拟代码(Descriptor.htm指出)

明白这些后, 再回到method与function的区别上.
为什么: M.func_or_method 和 M.__dict__['func_or_method'] 会不同呢?
使用dir()函数, 可以看到, M.func_or_method是有__get__属性的. 但是M.__dict__是没有.

也就是说: M.func_or_method已经被调用了func_or_method.__get__ ! 这样, type()打印出的东西已经是__get__返回的

按照上面了解的, 只是object和type调用__get__的参数不同. 并不是因为定义的函数中有self的原因!


总的来说: A.B都是使用A.__dict__字典, 至于调不调用字典返回的value的__get__和传给它的参数是什么由__getattribute__处理










Tuesday, November 17, 2009

看pydevd.py代码时碰到的问题

代码:
            #pretend pydevd is not the main module, and
            #convince the file to be debugged that it was loaded as main

            sys.modules['pydevd'] = sys.modules['__main__']
            sys.modules['pydevd'].__name__ = 'pydevd'            
            
            from imp import new_module
            m = new_module('__main__')
            sys.modules['__main__'] = m
            m.__file__ = file
            globals = m.__dict__

从这段代码中, 看到sys.modules和imp, 还有'__main__'

说白了, 不明白是什么意思!!!

上次学习, 本人知道每个文件(module)都为一个scope, global对是对于module的. module常常会有三个变量:
0. __package__ : 如果是import一个package的话, 这个变量就是包的名, 如果是module则为None
1. __name__ : 就是import时的名字, package时为包名, module则为模块名. 如果是__main__是指被python载入的文件(module)
2. __file__ : 不是每个import的对象都被这个变量的, 比如上面的imp包就没有, 还有就是直接运行 python 也是没有, 猜测: imp是不是py文件, 可以import入是因为它为python解释器内部的. 一些文档是这样写的: The __file__ attribute is not present for C modules that are
statically linked into the interpreter

虽然常用sys, 还还真少理会sys.module, 文档的解释:

modules
This is a dictionary that maps module names to modules which have already been loaded. This can be manipulated to force reloading of modules and other tricks. Note that removing a module from this dictionary is not the same as calling reload() on the corresponding module object.
看了其实也不是很明白. 只知道是Import入的包. 运行ptyhon(不是ipython):
>>> import sys, pprint
>>> pprint.pprint(sys.modules)
会发现有很多包不是自己import入的.

这个是python进程共import入的包, 已经不是具体某个包的scope了范围, 这种做法的意义: 让module对象可以被相互引用, 因为python进程存在这个变量都是存在的(当然需要import sys)

好了, 再回到最上面的代码, sys.modules['__main__']的含义:

jessinio@niolaptop ~/workspace/python script/src $ python
Python 2.6.2 (r262:71600, Oct 11 2009, 05:51:18)
[GCC 4.3.2] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> dir()
['__builtins__', '__doc__', '__name__', '__package__']
>>> print __name__
__main__
>>> import sys
>>> dir(sys.modules['__main__'])
['__builtins__', '__doc__', '__name__', '__package__', 'sys']
>>> print sys.modules['__main__'].__name__
__main__


明显是指python首个载入的文件, 因为每个py文件都是一个module, 所以就在这里出现了.

   sys.modules['pydevd'] = sys.modules['__main__']
   sys.modules['pydevd'].__name__ = 'pydevd'   
sys.modules['pydevd']和sys.modules['__main__']都是首个载入的文件(module)的引用 , 然后把首个载入的module scope内的__name__修改了. 这个__name__只是module内的变量

  from imp import new_module
  m = new_module('__main__')
  sys.modules['__main__'] = m
  m.__file__ = file
  globals = m.__dict__
使用API创建一个module对象(-_-!  还有这种玩法的! ) , 然后对外宣传为个新创建的module对象是首个载入的module. -_-! 算不算骗人? 不过还算好心, 还是给出了首个载入的module的路径(就是那个file变量)

了解后, 才明白最上面那段代码的commet是什么意思: 就是自己修改__main__防止被别人修改! 牛!!

下面是new_module的玩法:
>>> import imp
>>> a = imp.new_module('fuck')
>>> type(a)
<type 'module'>
>>> a.__name__
'fuck'

在我眼内, python里"_"开始的变量名都是淫技的开端! ( 不过还没, 淫技没有perl 淫, perl淫是那个乱! ), 淫技学少了会郁闷, 学多了又伤身, 只能适量!

下面学学__dict__这招. 提到__dict__就会扯到:
1. __solts__ : 限制__dict__的内容
2. __get__ : descriptor概念中使用的
3. __getattr__ : 老式的属性获取方法
4. __getattribute__ : 新式的属性获取方法
全是下划线!!

__dict__返回的符号首先与dir函数返回的符号的区别:
看dir()的说明:
      for a module object: the module's attributes.
      for a class object:  its attributes, and recursively the attributes
        of its bases.
      for any other object: its attributes, its class's attributes, and
        recursively the attributes of its class's base classes.
对于class和instane是有一个递归过程的, 抄祖宗十八代方式的.

>>> class C(object):
...     name = 'class'
...
>>> o = C()
>>> o.__dict__
{}
>>> o.name = 'instance name'
>>> o.__dict__
{'name': 'instance name'}

__dict__ 就是指self指的object自己的属性. 在python里, module, 每层class, instance的namespace就是__dict__
* 相关文档: http://pyref.infogami.com/__dict__

在最上面的代码中, 最后一句就容易理解了: globals = m.__dict__ 就是取得m对象的namespace全部变量, 它被应用于:
        if not IS_PY3K:
            execfile(file, globals, locals) #execute the script
        else:
            #We need to compile before so that the module name is correct
            obj = compile(open(file).read(), file, 'exec')
            exec(obj, globals, locals) #execute the script

当前运行模块(首个被载入的py文件)的CPU时间给了obj 对象使用. 偷吃也要擦嘴就顺便把namespace处理一把

关于在python进程都起作用的淫技应该被称为: Runtime service, 如下URL:
http://docs.python.org/library/python.html

Thursday, November 12, 2009

javascript的var关键字

var name = 'jessinio';
function foo() {
    alert(name);
    name = 'nio';
};

foo();
alert(name);

与其实语言对比, 上面的代码很容易理解: 就是alert一次, 再修改函数外面name变量的值, 这个值被称为全局变量. 在js中不需要global关键字来声明, 当如果这样呢:
var name = 'jessinio';
function foo() {
    alert(name);
    var name = 'nio';
};

foo();
alert(name);

多了红色的var . 比如python:
name = 'jessinio'
def foo():
    print name
    name = ""
foo()
 * 将会出错!

根据学习. js中的var这样:
1. 代码块中的var将使变量的作用范围局限于块中
2. js的全局变量说穿了就是window对象的属性. 例如:
var myfunc = function (){ my = 'global variable scope'};
myfunc()
alert(window.my);
* 增加global变量就是为window增加属性

什么是全局变量?

全局是一个范围, 这个早已经解理, 但是这个范围到底有多大?

就像我们的世界一样: 宇宙外面是什么? 全局包不包括宇宙外面?

只能说: global是相对的.
在python里, 这方面的API:
globals()
    globals() -> dictionary
    Return the dictionary containing the current scope's global variables.
locals()
Update and return a dictionary representing the current local symbol table.

存在run.py文件, 内容如下:
import a.am
a.am.foo()

这里存在四个scope区域:
1. run.py的scope
2. package a的scope
3. module am的scope
4. foo函数的scope

现在的问题是: 不同的scope中使用global声明和修改变量的值后是否会对其它scope产生影响

1. module中的function不会对引用它的scope产生影响 , 只会对module scope产生影响
在run.py文件中调用foo函数, foo函数中:
global name
name = "function set!"
结果发现module am的scope内的name变量变化. 这说明: function中的global声明和修改变量的值会影响到module的情况

2. package中的function不会对引用它的scope产生影响
在run.py中存在语句import a, 其中a/__init__.py的内容:
global name
name = '__init__.py set!'
结果在run.py中的scope没有发现. 这说明: package中的global声明和修改变量的值不会影响到引用它的scope
* 真实情况是: package中的function只是修改了__init__.py的scope. 这与(1)的情况是相同的


python中, 每个*.py都是一个module. package为组织module的一个对象, 说穿了package也为一个module, 例如:
# 主运行文件
jessinio@niolaptop /tmp/test $ cat use.py

import a.am
a.foo()
a.am.foo()
# pacakge的__init__.py文件
jessinio@niolaptop /tmp/test $ cat a/__init__.py
import pprint
def foo():
    print "package funcion"
# module文件
jessinio@niolaptop /tmp/test $ cat a/am.py
def foo():
    print "module am function"
# package这个绝对算是module!
jessinio@niolaptop /tmp/test $ python use.py
package funcion
module am function

在import入package下的module时, package这个"module" 也被import了! 这绝对叫到: 不正当捆绑型消费

每个python文件都会有下面的属性:
'__builtins__'
'__doc__'
'__file__'
'__name__'
'__package__'

package的__init__.py还会多一个属性:
'__path__'

Saturday, November 7, 2009

gentoo QA

刚开始, update world的时间, 也是来了一个QA打字的note. 没有注意, 然后把pidgin使用的eds USE标志去掉了.
因为这个USE需要evolution的. 就是在满足它的时候出了错误, 还正也不想安装evolution. 干脆去了它.

但是make了一小会, 又出了大致的错. 这一下提起注意, 因为错误大致有QA:
 * QA Notice: Package has poor programming practices which may compile
 *            fine but exhibit random runtime failures.
 * auevents.c:149: warning: incompatible implicit declaration of built-in function ‘free’
 * auevents.c:249: warning: incompatible implicit declaration of built-in function ‘free’
 * connection.c:569: warning: incompatible implicit declaration of built-in function ‘free’
 * connection.c:592: warning: incompatible implicit declaration of built-in function ‘free’

QA是什么?

G了一下, 得这个URL: http://www.gentoo.org/proj/en/qa/

难度是gentoo对包的要求过高了? 查了一把, 没有查到相关的配置

算了, 代码问题就不理会. 不然这级至少要半年才能升.

我搞不过, 还躲不过? 把这个包去掉再说!

BTW:: 每次升到QT就是烦!! 什么时候把QT也干废!