国产xxxx99真实实拍_久久不雅视频_高清韩国a级特黄毛片_嗯老师别我我受不了了小说

資訊專欄INFORMATION COLUMN

Memory Management and Circular References in Pytho

muddyway / 2336人閱讀

摘要:一般情況下,的垃圾收集器會被用于檢測上面這樣的循環(huán)引用,并刪除掉它們。你可以通過強(qiáng)制垃圾收集器運(yùn)行,并檢查列表里有什么來驗(yàn)證上述結(jié)論。

-- [since Python 3.4, circular references are handled much better](http://engineering.hearsaysocial.com/2013/06/16/circular-references-in-python/#comment-2882030670)

Nice post. Note that starting from Python 3.4, circular references are handled much better (docs imply it should be
rare that they are not collected -- but don"t give specifics about how to make that happen). For example the
example you give is no longer a problem in Python 3.5 (probably not in 3.4 either, but can"t test it right now).
前言

用像 Python, Ruby 這樣的解釋型語言編程很方便的一個方面就是,通常情況下,你可以避免處理內(nèi)存管理相關(guān)的事情。然而,有一個眾所周知的情況 Python 一定會有內(nèi)存泄漏,這就是當(dāng)你在對象創(chuàng)建中聲明了一個循環(huán)引用,而且在類聲明中實(shí)現(xiàn)了一個自定義的 __del__ 解構(gòu)方法。例如,考慮如下例子:

One of the more convenient aspects of writing code in interpreted languages such as Python or Ruby is that you normally can avoid dealing with memory management. However, one known case where Python will definitely leak memory is when you declare circular references in your object declarations and implement a custom __del__ destructor method in one these classes. For instance, consider the following example:

class A(object):
    def __init__(self, b_instance):
      self.b = b_instance

class B(object):
    def __init__(self):
        self.a = A(self)
    def __del__(self):
        print "die"

def test():
    b = B()

test()

當(dāng)函數(shù) test() 被調(diào)用時,它聲明了一個對象 B,在 B 的 __init__ 函數(shù)中,把自己當(dāng)成變量傳給了 A,A 然后在 __init__ 函數(shù)中聲明了對 B 的引用,這就造成了一個循環(huán)引用。一般情況下,python 的垃圾收集器會被用于檢測上面這樣的循環(huán)引用,并刪除掉它們。然而,因?yàn)樽远x的 ___del__ 方法,垃圾收集器會把這個循環(huán)引用相關(guān)對象標(biāo)記為 “uncollectable”。從設(shè)計(jì)上說,垃圾收集器并不知道循環(huán)引用對象的銷毀順序,所以也就不會去處理它們。你可以通過強(qiáng)制垃圾收集器運(yùn)行,并檢查 gc.garbage 列表里有什么來驗(yàn)證上述結(jié)論。

When the function test() is invoked, it declares an instance of B, which passes itself to A, which then sets a reference to B, resulting in a circular reference. Normally Python"s garbage collector, which is used to detect these types of cyclic references, would remove it. However, because of the custom destructor (the __del__ method), it marks this item as "uncollectable". By design, it doesn"t know the order in which to destroy the objects, so leaves them alone (see Python"s garbage collection documentation for more background). You can verify this aspect by forcing the Python garbage collector to run and inspecting what is set inside the gc.garbage array:

import gc
gc.collect()
print gc.garbage
[<__main__.B object at 0x7f59f57c98d0>]

你可以通過 objgraph 庫可視化這些循環(huán)引用。

You can also see these circular references visually by using the objgraph library, which relies on Python"s gc module to inspect the references to your Python objects. Note that objgraph library also deliberately plots the the custom __del__ methods in a red circle to spotlight a possible issue.

為了避免循環(huán)引用,你通常需要使用 weak reference,向 python 解釋器聲明:如果剩余的引用屬于 weak reference,或者使用了 context manager 或 with 語法,那么內(nèi)存可以被垃圾收集器回收并用于重新聲明對象。

To avoid circular references, you usually need to use weak references, declaring to the interpreter that the memory can be reclaimed for an object if the remaining references are of these types, or to use context managers and the with statement (for an example of this latter approach, see how it was solved for the happybase library).

find_circular_references.py
# -*- encoding: utf-8 -*-
from __future__ import print_function

import gc
import traceback
import types
from tornado import web, ioloop, gen
from tornado.http1connection import HTTP1ServerConnection


def find_circular_references(garbage=None):
    """
    從 garbage 中尋找循環(huán)引用
    """
    def inner(level):
        """
        處理內(nèi)層的數(shù)據(jù)
        """
        for item in level:
            item_id = id(item)
            if item_id not in garbage_ids:
                continue
            if item_id in visited_ids:
                continue
            if item_id in stack_ids:
                candidate = stack[stack.index(item):]
                candidate.append(item)
                found.append(candidate)
                continue

            stack.append(item)
            stack_ids.add(item_id)
            inner(gc.get_referents(item))
            stack.pop()
            stack_ids.remove(item_id)
            visited_ids.add(item_id)

    ######### 開始初始化 ########

    # 獲取傳入的 garbage 或者通過 gc 模塊獲取 garbage 列表
    garbage = garbage or gc.garbage

    # 已經(jīng)找到的循環(huán)引用列表 type: list of list
    found = []

    # 存放 item 的堆
    stack = []

    # 存放 item_id 的 set
    stack_ids = set()

    # 保存 garbage 里每個對象的 id
    garbage_ids = set(map(id, garbage))

    # 保存 visited item 的 id
    visited_ids = set()

    ######## 初始化結(jié)束 ########

    # 進(jìn)入遞歸函數(shù) inner
    inner(garbage)
    inner = None
    return found


class CollectHandler(web.RequestHandler):
    @gen.coroutine
    def get(self):
        # collect_result = None
        collect_result = gc.collect()
        garbage = gc.garbage
        # for i in garbage[:5]:
        #     print(gc.get_referents(i), "
")
        self.write("Collected: {}
".format(collect_result))
        self.write("Garbage: {}
".format(len(gc.garbage)))
        for circular in find_circular_references():
            print("
==========
 Circular 
==========")
            for item in circular:
                print("    ", repr(item))
            for item in circular:
                if isinstance(item, types.FrameType):
                    print("
Locals:", item.f_locals)
                    print("
Traceback:", repr(item))
                    traceback.print_stack(item)

class DummyHandler(web.RequestHandler):
    @gen.coroutine
    def get(self):
        self.write("ok
")
        self.finish()

application = web.Application([
    (r"/dummy/", DummyHandler),
    (r"/collect/", CollectHandler),
], debug=True)

if __name__ == "__main__":
    gc.disable()
    gc.collect()
    gc.set_debug(gc.DEBUG_STATS | gc.DEBUG_LEAK)
    print("GC disabled")

    print("Start on 8888")
    application.listen(8888)
    ioloop.IOLoop.current().start()

文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請注明本文地址:http://m.specialneedsforspecialkids.com/yun/40677.html

相關(guān)文章

  • 〔SPRING FRAMEWORK〕Dependencies

    摘要:每個屬性參數(shù)構(gòu)造函數(shù)中值的類型都能夠被成字符串類型。對比上文給出的個代碼片段,可發(fā)現(xiàn)皆在用不同的方法進(jìn)行元數(shù)據(jù)配置,并且被配置的具體對象是數(shù)據(jù)庫驅(qū)動。 @(SPRING FRAMEWORK) 〔4〕7.4 Dependencies 聲明: 斜體字:《官檔》原文 斜體加粗字:《官檔》原文的重點(diǎn)字、詞、句 正體字+前置〔〕:個人表述行為,如:〔總結(jié)〕、〔分析〕等 灰體字:生詞 粉體...

    MonoLog 評論0 收藏0
  • 【譯文】Node.js垃圾回收機(jī)制-基礎(chǔ)

    摘要:正好最近在學(xué)習(xí)的各種實(shí)現(xiàn)原理,在這里斗膽翻譯一篇垃圾回收機(jī)制原文鏈接。自動管理的機(jī)制中,通常都會包含垃圾回收機(jī)制。二垃圾回收機(jī)制的概念垃圾回收,是一種自動管理應(yīng)用程序所占內(nèi)存的機(jī)制,簡稱方便起見,本文均采用此簡寫。 最近關(guān)注了一個國外技術(shù)博客RisingStack里面有很多高質(zhì)量,且對新手也很friendly的文章。正好最近在學(xué)習(xí)Node.js的各種實(shí)現(xiàn)原理,在這里斗膽翻譯一篇Node...

    haobowd 評論0 收藏0
  • LogParser v0.8.0 發(fā)布:一個用于定期增量式解析 Scrapy 爬蟲日志的 Pytho

    摘要:開源安裝通過通過使用方法作為運(yùn)行請先確保當(dāng)前主機(jī)已經(jīng)安裝和啟動通過命令啟動訪問假設(shè)運(yùn)行于端口訪問以獲取某個爬蟲任務(wù)的日志分析詳情配合實(shí)現(xiàn)爬蟲進(jìn)度可視化詳見在代碼中使用 GitHub 開源 my8100 / logparser 安裝 通過 pip: pip install logparser 通過 git: git clone https://github.com/my8100/logp...

    Object 評論0 收藏0
  • JavaScript深入淺出第3課:什么是垃圾回收算法?

    摘要:摘要是如何回收內(nèi)存的深入淺出系列深入淺出第課箭頭函數(shù)中的究竟是什么鬼深入淺出第課函數(shù)是一等公民是什么意思呢深入淺出第課什么是垃圾回收算法最近垃圾回收這個話題非常火,大家不能隨隨便便的扔垃圾了,還得先分類,這樣方便對垃圾進(jìn)行回收再利用。 摘要: JS是如何回收內(nèi)存的? 《JavaScript深入淺出》系列: JavaScript深入淺出第1課:箭頭函數(shù)中的this究竟是什么鬼? Jav...

    AaronYuan 評論0 收藏0
  • [譯]JavaScript是如何工作的:內(nèi)存管理以及如何處理四種常見的內(nèi)存泄漏

    摘要:是如何工作的內(nèi)存管理以及如何處理四種常見的內(nèi)存泄漏原文譯者幾個禮拜之前我們開始一系列對于以及其本質(zhì)工作原理的深入挖掘我們認(rèn)為通過了解的構(gòu)建方式以及它們是如何共同合作的,你就能夠?qū)懗龈玫拇a以及應(yīng)用。 JavaScript是如何工作的:內(nèi)存管理以及如何處理四種常見的內(nèi)存泄漏 原文:How JavaScript works: memory management + how to han...

    tianren124 評論0 收藏0

發(fā)表評論

0條評論

最新活動
閱讀需要支付1元查看
<