2013年5月17日 星期五

Python: with...as

在python的世界當中,try...except...finally語句(statement)可以由with...as語句來替代。

grammar:

with expression as variable:

with一開始執行時(尚未執行expression),會執行__enter__()方法,而該方法所回傳的物件,可以使用as指令給另一個變數來參考(如果有的話),接著執行with區塊內的expression程式碼。

Python的yield

先從Python Official Documentation看起對於yield的解釋

Python 2.7.5 version definition (python2.7.5好像還是視yield為statement?????)

6.8. The yield statement

yield_stmt ::=  yield_expression
The yield statement is only used when defining a generator function, and is only used in the body of the generator function. Using a yieldstatement in a function definition is sufficient to cause that definition to create a generator function instead of a normal function.
When a generator function is called, it returns an iterator known as a generator iterator, or more commonly, a generator. The body of the generator function is executed by calling the generator’s next() method repeatedly until it raises an exception.
When a yield statement is executed, the state of the generator is frozen and the value of expression_list is returned to next()‘s caller. By “frozen” we mean that all local state is retained, including the current bindings of local variables, the instruction pointer, and the internal evaluation stack: enough information is saved so that the next time next() is invoked, the function can proceed exactly as if the yield statement were just another external call.
As of Python version 2.5, the yield statement is now allowed in the try clause of a try ... finally construct. If the generator is not resumed before it is finalized (by reaching a zero reference count or by being garbage collected), the generator-iterator’s close() method will be called, allowing any pending finally clauses to execute.
For full details of yield semantics, refer to the Yield expressions section.
Note

In Python 2.2, the yield statement was only allowed when the generators feature has been enabled. This __future__ import statement was used to enable the feature:
from __future__ import generators



Generators和yield之間的關係:

'yield'從python2.5開始,由statement轉成expression。而'yield'就像function的return value一樣,能回傳值出來,但本身又不會結束函式的執行(除非已執行到函式結束為止,才會丟exception)。因為yield只是暫時轉換執行的控制權,並回傳值給原本呼叫它的程式(caller),所以才可以利用yield來產生一系列的值,而擁有'yield'的函式 (function)我們稱之為"generator function(生成器函式)",而yield本身就像是generator function的return一樣。

"Yield," however, implies that the transfer of control is temporary and voluntary, and our function expects to regain it in the future.
In Python, "functions" with these capabilities are called generators, and they're incredibly useful.generators (and the yield statement) were initially introduced to give programmers a more straightforward way to write code responsible for producing a series of values. 

  • generators are used to generate a series of values
  • yield is like the return of generator functions
  • The only other thing yield does is save the "state" of a generator function
  • A generator is just a special type of iterator
  • Like iterators, we can get the next value from a generator using next()
    • for gets values by calling next() implicitly


yield (生成器)好似是個比較難理解的概念.
當這個生成器被執行時.將會回傳一個 itertor.
之後便可以通過 next() 或者是 send(something) 來呼叫
而他執行後會記住上一次的執行結果..之後再繼續執行 




再從良葛格筆記看'yield'的解釋:




從Python 2.5開始,yield從陳述句(statement)改為運算式(expression),也就是yield除了「產生」指定的值之外,會有一個運算結果,yield運算結果預設是None,你可以透過產生器的send()方法傳入一個值,這個值就成為yield的運算結果。這給了你一個與產生器溝通的機會。例如:

>>> def myrange(n):
...     x = 0
...     while True:
...         val = (yield x)
...         if val is not None:
...             x = val
...         else:
...             x += 1
...         if x >= n:
...             break
...
>>> g = myrange(10)
>>> next(g)
0
>>> next(g)
1
>>> next(g)
2
>>> g.send(0)
0
>>> next(g)
1
>>> next(g)
2
>>> g.send(5)
5
>>> next(g)
6
>>> next(g)
7
>>>





Reference:

1. http://openhome.cc/Gossip/Python/YieldGenerator.html
2. Improve your Python: 'yield' and 'generator' explained, http://www.jeffknupp.com/blog/2013/04/07/improve-your-python-yield-and-generators-explained/

2013年5月16日 星期四

Python的繼承

Python是多重繼承的關係


http://pydoing.blogspot.tw/2011/01/python-multiple.html

Cinder: cinder/volume/drivers/xenapi/lib.py


in cinder/volume/drivers/xenapi/lib.py (from grizzly version )


XenAPISession

     |- ContextAwareSession

       |- OpenStackXenAPISession



CompoundOperations


    |- NFSOperationsMixIn




https://bitbucket.org/ncupdclab/sameved-cinder/src/2bc06f23ebfa63b95ca68bb0840df51c267208ce/volume/drivers/xenapi/lib.py?at=master

Citrix Xenserver VDI type


Type:enum vdi_type
ValueDescription
systema disk that may be replaced on upgrade
usera disk that is always preserved on upgrade
ephemerala disk that may be reformatted on upgrade
suspenda disk that stores a suspend image
crashdumpa disk that stores VM crashdump information
Name:type
type of the VDI
Field is read-only



http://docs.vmd.citrix.com/XenServer/4.0.1/api/docs/html/browser.html

Python: contextlib - Utilities for with-statement contexts

This module provides utilities for common tasks involving the with statement. For more information see also Context Manager Types and With Statement Context Managers.


http://docs.python.org/2/library/contextlib.html

2013年5月15日 星期三

查閱XeAPI當中的session物件以及xenapi物件底下的method



#!/usr/bin/env python

import sys
import XenAPI
import pprint
import inspect

if __name__ == "__main__":
    url = sys.argv[1]
    username = sys.argv[2]
    password = sys.argv[3]

    session = XenAPI.Session(url)
    session.xenapi.login_with_password(username,password)
    print session.__dict__.items()
    print session.xenapi.__dict__.items()



root@StorageController:[~/xenapi-test](master) 4h5m $ python vdi-create.py https://ip:443  account password

[('last_login_method', 'login_with_password'), ('_ServerProxy__transport', <xmlrpclib.SafeTransport instance at 0x7f4a7640ccb0>), ('_ServerProxy__handler', '/RPC2'), ('_ServerProxy__host', '<ip>:443'), ('last_login_params', ('<acccount>', '<password>')), ('_ServerProxy__verbose', 0), ('_ServerProxy__allow_none', 1), ('_session', 'OpaqueRef:35bd0f38-b821-af71-eb26-e151370c6337'), ('API_version', '1.8'), ('_ServerProxy__encoding', None), ('transport', None)]

[('_Dispatcher__API_version', '1.8'), ('_Dispatcher__send', <bound method Session.xenapi_request of <ServerProxy for <ip>:443/RPC2>>), ('_Dispatcher__name', None)]

Python: try...except

在python當中,例外處裡(Exception Handling)是用try...except敘述句來完成,不同於C++/Java當中的try...catch語句。但我有時會覺得疑惑except不是有"除此...之外"的意思嗎?!但這裡的except是當及物動詞使用,可以視為"丟出...的例外"的意思。(思維: 因為exception是例外,如果把它動詞化的話except就是"丟出...的例外"的意思)



Python


try:
     // Code here to try

except Exception:
      // Exception Handling



raise

再來看看raise的使用,正如在 try 陳述句 中看到的,你可以在raise後接上字串或例外類別名稱,現在已不鼓勵raise字串實例。實際上,raise之後可以接上例外類別名稱、例外實例或不接上任何東西。

當你在raise後接上例外類別時,實際上會以該類別建立實例再丟出,也就是下面兩行程式碼的作用是相同的:

raise EOFError
raise EOFError()

如果在except中使用raise而不接上任何物件,則表示將except比對到的例外實例再度丟出。例如:

>>> try:
...     raise EOFError
... except EOFError:
...     print('got it')
...     raise
...
got it
Traceback (most recent call last):
  File "<stdin>", line 2, in <module>
EOFError
>>>

如果必要的話,你還可以在except中raise例外時,附上except所比對到的例外實例。例如。
>>> try:
...     raise EOFError
... except EOFError as e:
...     print('got it')
...     raise IndexError from e
...
got it
Traceback (most recent call last):
  File "<stdin>", line 2, in <module>
EOFError

The above exception was the direct cause of the following exception:

Traceback (most recent call last):
  File "<stdin>", line 5, in <module>
IndexError
>>>


raise from語法,會將from後接上的例外實例,設定給被raise的例外實例之__cause__。例如:
>>> try:
...     try:
...         raise EOFError('XD')
...     except EOFError as e:
...         print(e.args)
...         raise IndexError('Orz') from e
... except IndexError as e:
...     print(e.args)
...     print(e.__cause__.args)
...
('XD',)
('Orz',)
('XD',)
>>>


實際上,如果你在except中raise某個例外,則原except所比對到的例外,無論有無使用raise from,都會自動設定給__context__。例如:
>>> try:
...     try:
...         raise EOFError('XD')
...     except EOFError as e:
...         print(e.args)
...         raise IndexError('Orz') from e
... except IndexError as e:
...     print(e.args)
...     print(e.__cause__.args)
...     print(e.__context__.args)
...

('XD',)
('Orz',)
('XD',)
('XD',)
>>>




Reference:
http://docs.python.org/2/tutorial/errors.html
http://caterpillar.onlyfun.net/Gossip/Python/TryRaise.html

Python: logging module


Logging module

logging module可以分成logger、handler、formatter等三大元件。

LevelWhen it’s used
DEBUGDetailed information, typically of interest only when diagnosing problems.
INFOConfirmation that things are working as expected.
WARNINGAn indication that something unexpected happened, or indicative of some problem in the near future (e.g. ‘disk space low’). The software is still working as expected.
ERRORDue to a more serious problem, the software has not been able to perform some function.
CRITICALA serious error, indicating that the program itself may be unable to continue running.


LevelNumeric value
CRITICAL50
ERROR40
WARNING30
INFO20
DEBUG10
NOTSET0

NOTEST < DEBUG < INFO < WARNING < ERROR < CRITICAL

如果把debug level設置為INFO,則<INFO的log將不會輸出,只有>= INFO的log才會輸出。


Logger.debug(msg [ ,*args [, **kwargs]])

  记录DEBUG级别的日志信息。参数msg是信息的格式,args与kwargs分别是格式参数。
[python] view plaincopy
  1. import logging  
  2. logging.basicConfig(filename = os.path.join(os.getcwd(), 'log.txt'), level = logging.DEBUG)  
  3. log = logging.getLogger('root')  
  4. log.debug('%s, %s, %s', *('error', 'debug', 'info'))  
  5. log.debug('%(module)s, %(info)s', {'module': 'log', 'info': 'error'})  

Logger.info(msg[ , *args[ , **kwargs] ] )

Logger.warnning(msg[ , *args[ , **kwargs] ] )

Logger.error(msg[ , *args[ , **kwargs] ] )

Logger.critical(msg[ , *args[ , **kwargs] ] )

  记录相应级别的日志信息。参数的含义与Logger.debug一样。

logger.conf

qualname

he qualname entry is the hierarchical channel name of the logger, that is to say the name used by the application to get the logger.



































Reference:
1. python logging module 入門, http://blog.csdn.net/jgood/article/details/4340740
2. http://www.icoding.co/2012/08/logging-html

Python: sys.exc_info()



sys.exc_info()


This function returns a tuple of three values that give information about the exception that is currently being handled. The information returned is specific both to the current thread and to the current stack frame. If the current stack frame is not handling an exception, the information is taken from the calling stack frame, or its caller, and so on until a stack frame is found that is handling an exception. Here, “handling an exception” is defined as “executing or having executed an except clause.” For any stack frame, only information about the most recently handled exception is accessible.
If no exception is being handled anywhere on the stack, a tuple containing three None values is returned. Otherwise, the values returned are (type, value, traceback). Their meaning is: type gets the exception type of the exception being handled (a class object); value gets the exception parameter (its associated value or the second argument to raise, which is always a class instance if the exception type is a class object); traceback gets a traceback object (see the Reference Manual) which encapsulates the call stack at the point where the exception originally occurred.

If exc_clear() is called, this function will return three None values until either another exception is raised in the current thread or the execution stack returns to a frame where another exception is being handled.


Warning

Assigning the traceback return value to a local variable in a function that is handling an exception will cause a circular reference. This will prevent anything referenced by a local variable in the same function or by the traceback from being garbage collected. Since most functions don’t need access to the traceback, the best solution is to use something like exctype, value = sys.exc_info()[:2] to extract only the exception type and value. If you do need the traceback, make sure to delete it after use (best done with a try ... finally statement) or to call exc_info() in a function that does not itself handle an exception.
Note

Beginning with Python 2.2, such cycles are automatically reclaimed when garbage collection is enabled and they become unreachable, but it remains more efficient to avoid creating cycles.


Reference:
1. http://docs.python.org/2/library/sys.html

Python Runtime Service



http://docs.python.org/2/library/python.html

Python : all() 判斷參數是否為迭代器(iterator)




http://pydoing.blogspot.tw/2011/02/python-all_20.html

Nova rootwrap

使用root wrapper可以让非特权用户以root身份尽可能安全地执行部分操作。nova曾经使用sudoers文件来列出允许执行的特权命令,使用sudo来运行这么命令,但是这样不容易维护,而且不能进行复杂的参数处理,rootwrap就是为了解决这些问题。
使用sudo nova-rootwrap config-file command,而不再是使用sudo command。只需要使用一个通用的sudoers使nova-rootwrap以root身份运行。nova-rootwrap查看配置文件,加载command filters,检查请求的命令是否匹配某个filter,如果匹配就以root身份运行,否则就拒绝请求。



Reference:

2013年5月14日 星期二

Python: _() 的用途


_在Django中是為了i18n(internationalization)的目的,為了將字串轉譯成其他語言。




http://stackoverflow.com/questions/3967231/whats-the-meaning-of-in-python

Python - “_” Argument to functions



In the interactive interpreter _ is used to reference the last returned value


Eg
>>> 2 + 4
6
>>> _ + 4
10
So you can use it as an argument in a function as well
>>> 2 + 4
6
>>> for i in range(_): print(i)
0
1
2
3
4
5




http://stackoverflow.com/questions/10232404/python-argument-to-functions