找到目录 python 的文章 8 篇.


Python内存分配和垃圾回收

Posted on 2017-05-17 03:24:16 python

摘要:

Python内存分配和垃圾回收

阅读全文

Greenlet简介

Posted on 2014-02-12 08:11:23 python

摘要:

一个 greenlet 是一个很小的独立微线程。可以把它想像成一个堆栈帧,栈底是初始调用,而栈顶是当前greenlet的暂停位置。你使用greenlet创建一堆这样的堆 栈,然后在他们之间跳转执行。跳转不是绝对的:一个greenlet必须选择跳转到选择好的另一个greenlet,这会让前一个挂起,而后一个恢复。两 个greenlet之间的跳转称为 切换(switch) 。

当你创建一个greenlet,它得到一个初始化过的空堆栈;当你第一次切换到它,他会启动指定的函数,然后切换跳出greenlet。当最终栈底 函数结束时,greenlet的堆栈又编程空的了,而greenlet也就死掉了。greenlet也会因为一个未捕捉的异常死掉。

阅读全文

一种新的python局部调试手法

Posted on 2014-01-28 12:47:57 python

我们都知道,python里面可以用pdb来调试代码。但是pdb往往不大好用。有时候调试代码往往在多重条件里面,直接用pdb需要下条件断点,设定复杂的条件。

一个简单的办法就是这么干。

__import__('pdb').set_trace()

但是有的时候,连这个出现的条件都不满足。例如,代码必须在一个受限环境中运行,很难拿到console,或者其他林林总总的毛病。这时候,我们还有一招秘技。

import pdb, socket
s = socket.socket()
s.connect(('127.0.0.1', 8888))
f = s.makefile()
pdb.Pdb(stdin=f, stdout=f).set_trace()

在连接到的目标端口上,提前用nc做好监听,就可以在触发断点的时候直接连接上来调试。


线程同步思考 - Condition模块

Posted on 2013-05-08 17:38:07 python

1. python的threading模块的Condition类提供了通过条件变量保持多个线程间同步. 一个线程阻塞,等待从其他线程获取通知。
2. 假设有两个线程A和B,线程A首先执行wait(),线程B再执行notify()。线程A从Condition对象上得到通知,wait()函数获取到锁,往下继续执行。
3. 此时线程B再次执行notify(),但此时线程A正在运行wait()之后的代码,没有执行wait()。线程B执行的notify(),会是怎样的结果?

根据查看代码和文档,猜测可能会有以下结果:

线程B报错,没有waiter(这是从源码中看到的)。

如何解决?

1. 线程A的wait()后面的代码应尽快执行完毕,让线程A尽快在下个循环中进入wait()等待。
2. 根据实际业务需求,线程B应尽量避免没有线程在wait()的时候,执行notify()。

这么看来,还是后面这个方法靠谱一些。 Condition类的notify()只管通知,至于有没有线程在wait(),它就不管了(最多只报错).


python的参数传递机制

Posted on 2012-12-15 01:47:04 python

调用函数时,函数参数仅仅是引用传入对象的名称。

参数传递的基本语义和其他编程语言中已知的方式不完全相同。

例如“按值传递” 或 “按引用传递”。

例如,如果传递不可变的值(如tuple、string list),参数看起来实际是按值传递的。

但如果传递可变变量(如列表或字典)给函数,然后再修改次可变对象,这些改动就会反映在原始对象中。

像这样悄悄修改其输入值或者程序其他部分的函数具有副作用。一般来说,最好避免使用这种编程风格,因为随着程序的规模和复杂度不断增加,这类函数会成为各种奇怪编程错误的来源。(例如,如果函数具有副作用,只看函数调用是无法明显找到问题的。)

在设计线程和并发性的程序中,使用此类函数的效率很低,因为通常需要使用锁定来防止副作用的影响。 多线程环境中,对于每个run函数如果显示修改一个全局变量(一个字典),那么需要为每个线程加锁。 一般的办法就是直接return新变量,而不是“原地修改”


python线程的又一细节

Posted on 2012-12-03 17:37:45 python

首先,在python的线程中,任何在run函数中调用的代码,都是运行在新线程中。

其他的实例方法,全部运行在主线程中。

上代码:

#!/usr/bin/python
# -- coding: utf-8 --

import threading
import signal
import time

# 注意:run函数中执行的代码都是在新线程中
# 而hander方法在主线程中,可以查看它们的thread id

def thread_sig():
    # 在子线程中发送信号
    signal.alarm(3)

class ihander(threading.Thread):
    def __init__(self):
        super(ihander, self).__init__()
        print threading.currentThread(), " in __init__"
        signal.signal(signal.SIGALRM, self.handler)
    
    def run(self):
        print threading.currentThread(), " in run"
        time.sleep(10)
    
    def handler(self, signum, frame):
        print threading.currentThread(), " in handler"
        print 'signal: ', signum

h = ihander()
h.start()

t = threading.Thread(target=thread_sig, args=())
t.start()

执行结果:

<_MainThread(MainThread, started 139779179116288)>  in __init__
<ihander(Thread-1, started 139779145524992)>  in run
<_MainThread(MainThread, stopped 139779179116288)>  in handler
signal:  14

我们如果把signal.signal放在其他线程中,就会出错:

def thread_sig():
    # 在子线程中发送信号
    signal.alarm(3)
    signal.signal(signal.SIGALRM, h.handler)

class ihander(threading.Thread):
    def __init__(self):
        super(ihander, self).__init__()
        print threading.currentThread(), " in __init__"
    
    def run(self):
        print threading.currentThread(), " in run"
        time.sleep(10)
    
    def handler(self, signum, frame):
        print threading.currentThread(), " in handler"
        print 'signal: ', signum

执行结果是:

Exception in thread Thread-2:
Traceback (most recent call last):
  File "/usr/lib/python2.7/threading.py", line 551, in __bootstrap_inner
    self.run()
  File "/usr/lib/python2.7/threading.py", line 504, in run
    self.__target(*self.__args, **self.__kwargs)
  File "/data/tornado_analyst/test_signal.py", line 14, in thread_sig
    signal.signal(signal.SIGALRM, h.handler)
ValueError: signal only works in main thread

python报告说,signal只能工作在主线程中。

下面是一些关于python中信号的注意点:

/*
   NOTES ON THE INTERACTION BETWEEN SIGNALS AND THREADS

   When threads are supported, we want the following semantics:

   - only the main thread can set a signal handler
   - any thread can get a signal handler
   - signals are only delivered to the main thread

   I.e. we don't support "synchronous signals" like SIGFPE (catching
   this doesn't make much sense in Python anyway) nor do we support
   signals as a means of inter-thread communication, since not all
   thread implementations support that (at least our thread library
   doesn't).

   We still have the problem that in some implementations signals
   generated by the keyboard (e.g. SIGINT) are delivered to all
   threads (e.g. SGI), while in others (e.g. Solaris) such signals are
   delivered to one random thread (an intermediate possibility would
   be to deliver it to the main thread -- POSIX?).  For now, we have
   a working implementation that works in all three cases -- the
   handler ignores signals if getpid() isn't the same as in the main
   thread.  XXX This is a hack.

   GNU pth is a user-space threading library, and as such, all threads
   run within the same process. In this case, if the currently running
   thread is not the main_thread, send the signal to the main_thread.
*/

pdb常用调试命令

Posted on 2012-11-30 18:30:54 python

摘要:

h(elp),会打印当前版本Pdb可用的命令,如果要查询某个命令,可以输入 h [command],例如:“h l” — 查看list命令 l(ist),可以列出当前将要运行的代码块

阅读全文

关于python装饰器的总结

Posted on 2012-05-08 12:23:39 python

# 因为wrap函数的参数只能是一个函数
# 而wrapper的参数又只能是传递给函数的参数列表
# 如果想要再次处理被装饰函数的返回结果,只能在最外层的函数参数中指定
# 这里就是在deco函数的参数中
# 如果只用两层嵌套就无法做到
def deco(render=None):
    def wrap(func):
        def wrapper(*args,**kwargs):
            result = func(*args,**kwargs) ###
            return render(result)  ###
        return wrapper
    return wrap


my_render = lambda x: str(x) + ' --my_render'

@deco(render=my_render)
def test():
    return "this is test!"

print test()

这里正是因为想让result被再次处理,所以要在最外层函数的参数中制定调用的处理函数,就是my_render。