标签: cpython

如何将func_closure条目映射到变量名称?

我有一个在此函数中创建的lambda对象:

def add_url_rule(self, rule, endpoint=None, view_func=None, **options):
    self.record(lambda s:
        s.add_url_rule(rule, endpoint, view_func, **options))
Run Code Online (Sandbox Code Playgroud)

使用func_closurelambda函数对象,我可以访问lambda函数的闭包范围:

(<cell at 0x3eb89f0: str object at 0x2fb4378>,
 <cell at 0x3eb8a28: function object at 0x3cb3a28>,
 <cell at 0x3eb8a60: str object at 0x3ebd090>,
 <cell at 0x3eb8b08: dict object at 0x3016ec0>)
Run Code Online (Sandbox Code Playgroud)

仔细观察(cell_contents每个cell对象的属性)向我展示:

>>> [c.cell_contents for c in func.func_closure]
['categoryDisplay',
 <function indico.web.flask.util.RHCategoryDisplay>,
 '/<categId>/',
 {}]
Run Code Online (Sandbox Code Playgroud)

lambda函数是由这个调用创建的:

add_url_rule('/<categId>/', 'categoryDisplay', rh_as_view(RHCategoryDisplay))
Run Code Online (Sandbox Code Playgroud)

如您所见,顺序与函数的参数顺序或lambda中使用参数的顺序不匹配.虽然我可以根据其类型/内容轻松找出哪个元素是什么,但我想以更清洁的方式进行.

所以我的问题是:如何将它与原始变量名称相关联(或者至少在函数参数的情况下位置)?

python cpython python-2.x

7
推荐指数
2
解决办法
1732
查看次数

字符串没有被dicts引用?

看看这个Python代码:

from gc import get_referrers as refs
x = 'x'
d = {x:x}
print(d in refs(x))
Run Code Online (Sandbox Code Playgroud)

它打印False.这本身就很奇怪,但是当你考虑以下因素时变得更加怪异:

  • 如果x是一个数字(int,float,complex,Fraction,Decimal)而不是字符串,它仍然会打印False.对于字节和bytearray也是如此.但是对于其他所有类型(如果用作键,可以使用,如tuple或frozenset,还有许多其他类型,如果仅用作值),则会打印True.

  • 如果d是包含x的任何其他容器(set,list,tuple ...),则输出True.只有dict,它打印False.此外,如果x是键或值,或者如上所述,两者都无关紧要.

我认为在Python中,每个对象都是一个引用(而不是Java,它有原始类型,或者Ruby,它是值类型小的int),但现在看起来str和int是有点原始的类型,没有被引用.但另一方面,为什么只有在说?

我也知道在CPython中缓存了从-5到256的整数(并且可以实现小字符串),因此不重新计算它们是有意义的,因为它们永远不会被删除,但这适用于任何整数(和长字符串)我试过,比那个范围大得多.

有谁知道这里发生了什么?

---更新---

Curiouser和curiouser ......似乎是datetime.{datetime,date,time}类具有相同的"未引用"行为.现在,我知道有一件事,AnyStr和Number有一个共同点:他们的哈希值是随机的,每个会话的盐.但这没有任何意义,因为即使这些行为仅仅是词汇中的值而不是键,也会观察到行为.价值观并没有散播.或者是他们?

python string dictionary cpython reference

7
推荐指数
1
解决办法
92
查看次数

Python存储函数闭包的名称绑定在哪里?

所以最近我理解了函数闭包的概念.

def outer():
    somevar = []
    assert "somevar" in locals() and not "somevar" in globals()
    def inner():
        assert "somevar" in locals() and not "somevar" in globals()
        somevar.append(5)
        return somevar
    return inner

function = outer()
somevar_returned = function()
assert id(somevar_returned) == id(function.func_closure[0].cell_contents)
Run Code Online (Sandbox Code Playgroud)

根据我的理解,函数闭包的目的是保持对对象的活动引用,以避免垃圾收集此对象.这就是为什么以下工作正常:

del outer
somevar_returned_2 = function()
assert id(somevar_returned) == id(function.func_closure[0].cell_contents)
assert id(somevar_returned) == id(somevar_returned_2)
Run Code Online (Sandbox Code Playgroud)

在执行inner函数之前,事情是(总是和我理解的一样),Python重建了locals变量字典.这本词典将包含:

  • 函数的闭包名称与其单元格内容相关联
  • 函数的参数名称与其默认值或给定的参数相关联(并且它可以覆盖先前的名称)

问题是Python存储闭包的名称绑定在哪里?我找不到任何地方.

注意:函数的属性:

>>> print "\n".join("%-16s : %s" % (e, getattr(function, e)) for e in dir(function) if not e.startswith("_") and e …
Run Code Online (Sandbox Code Playgroud)

python closures cpython python-2.x

7
推荐指数
1
解决办法
517
查看次数

为什么getpwuid和getgrgid会有不同的行为?

在Python 2.7,3.4和3.5中,grp.getgrgid能够接受一个字符串:

from grp import getgrgid
print(getgrgid('0'))
Run Code Online (Sandbox Code Playgroud)

但是,pwd.getpwuid不能这样做:

from pwd import getpwuid
print(getpwuid('0'))

Traceback (most recent call last):
  File "getpwuid_test.py", line 2, in <module>
    print(getpwuid('0'))
TypeError: an integer is required
Run Code Online (Sandbox Code Playgroud)

这是因为在内部Modules/pwdmodule.c,getpwuid使用PyNumber_ParseTuple转换器PyNumber_Index来获取Python整数,并在失败时引发异常.

然而,在Modules/grpmodule.c,grp_getgrgid应用PyNumber_Long (或者PyNumber_Int一个老足够的Python)作为转换第一,并作为文件说,在https://docs.python.org/3/c-api/number.html,这是运行的等效int(o),可以将字符串转换为整数.只有这样才能PyNumber_Index通过辅助函数给予它_Py_Gid_Converter

造成这种差异的原因是什么?这是基于历史的故意选择吗?

这种行为getgrgid似乎更有帮助,奇怪的是它并不适用于这两种功能.在这种不良行为getgrgid或getpwuid?

python cpython python-2.7 python-3.x

7
推荐指数
1
解决办法
379
查看次数

Python2词典中的非单调内存消耗

有人可以解释CPython 2.7中字典的非单调内存使用吗?

>>> import sys
>>> sys.getsizeof({})
280
>>> sys.getsizeof({'one': 1, 'two': 2, 'three': 3, 'four': 4, 'five': 5})
280
>>> sys.getsizeof({'one': 1, 'two': 2, 'three': 3, 'four': 4, 'five': 5, 'six': 6})
1048
>>> sys.getsizeof({'one': 1, 'two': 2, 'three': 3, 'four': 4, 'five': 5, 'six': 6, 'seven': 7})
1048
>>> sys.getsizeof({'one': 1, 'two': 2, 'three': 3, 'four': 4, 'five': 5, 'six': 6, 'seven': 7, 'e
ight': 8})
664
>>> sys.getsizeof({'one': 1, 'two': 2, 'three': 3, 'four': 4, 'five': 5, …
Run Code Online (Sandbox Code Playgroud)

python memory cpython python-2.7 python-internals

7
推荐指数
1
解决办法
113
查看次数

在windbg中调试python转储文件

我的一个python.exe(v3.5.2)进程挂起在远程Windows Server中.我无法从远程站点附加它,因此我创建了一个完整的内存转储并将其下载回分析.

但是,windbg在gdb中没有像py-bt这样的工具.我能做的是下载cpython符号文件并加载到windbg.

问题是: 如何打印python脚本调用堆栈就像"py-bt"一样?

调用堆栈如下所示,看起来像挂在HTTPS连接上

0:000> k
ChildEBP RetAddr  
0050dd24 74592242 ntdll!ZwWaitForSingleObject+0xc
0050dd6c 7459bdee mswsock!SockWaitForSingleObject+0x143
0050ddf8 777561e0 mswsock!WSPRecv+0x391
0050de48 614d8e76 ws2_32!recv+0x103
0050de68 614138bb _ssl!sock_read+0x26 [c:\build\cpython\externals\openssl-1.0.2h\crypto\bio\bss_sock.c @ 141]
0050de90 614bc229 _ssl!BIO_read+0x5b [c:\build\cpython\externals\openssl-1.0.2h\crypto\bio\bio_lib.c @ 210]
0050debc 614bc36e _ssl!ssl3_read_n+0x1c9 [c:\build\cpython\externals\openssl-1.0.2h\ssl\s3_pkt.c @ 255]
0050df78 614bd136 _ssl!ssl3_get_record+0x9e [c:\build\cpython\externals\openssl-1.0.2h\ssl\s3_pkt.c @ 339]
0050dfb8 614c0bb5 _ssl!ssl3_read_bytes+0x1a6 [c:\build\cpython\externals\openssl-1.0.2h\ssl\s3_pkt.c @ 1228]
0050dfdc 614c0c13 _ssl!ssl3_read_internal+0x45 [c:\build\cpython\externals\openssl-1.0.2h\ssl\s3_lib.c @ 4459]
0050dfec 61402880 _ssl!ssl3_read+0x13 [c:\build\cpython\externals\openssl-1.0.2h\ssl\s3_lib.c @ 4483]
0050e034 613ff8f7 _ssl!_ssl__SSLSocket_read_impl+0x1f0 [c:\build\cpython\modules\_ssl.c @ 1944]
0050e080 61b12ae3 _ssl!_ssl__SSLSocket_read+0x67 [c:\build\cpython\modules\clinic\_ssl.c.h @ 267]
0050e09c 61b7409f python35!PyCFunction_Call+0x113 [c:\build\cpython\objects\methodobject.c …
Run Code Online (Sandbox Code Playgroud)

python debugging windbg cpython

7
推荐指数
1
解决办法
1031
查看次数

如果我使用自定义dict作为函数的全局变量,为什么我不能访问builtins?

我有一个dict像这样的子类:

class MyDict(dict):
    def __getitem__(self, name):
        return globals()[name]
Run Code Online (Sandbox Code Playgroud)

这个类可以使用eval和exec不使用问题:

>>> eval('bytearray', MyDict())
<class 'bytearray'>
>>> exec('print(bytearray)', MyDict())
<class 'bytearray'>
Run Code Online (Sandbox Code Playgroud)

但是如果我用types.FunctionType构造函数实例化一个函数对象,该函数就无法访问任何内置函数:

import types

func = lambda: bytearray
func_copy = types.FunctionType(func.__code__,
                              MyDict(),
                              func.__name__,
                              func.__defaults__,
                              func.__closure__)

print(func_copy())
# Traceback (most recent call last):
#   File "untitled.py", line 16, in <module>
#     print(func_copy())
#   File "untitled.py", line 8, in <lambda>
#     func = lambda: bytearray
# NameError: name 'bytearray' is not defined
Run Code Online (Sandbox Code Playgroud)

替换MyDict()为globals() …

python global cpython function

7
推荐指数
1
解决办法
98
查看次数

Debug the CPython opcode stack

CPython 3.7 introduced the ability to step through individual opcodes in a debugger. However, I can't figure out how to read variables out of the bytecode stack.

For example, when debugging

def f(a, b, c):
    return a * b + c

f(2, 3, 4)
Run Code Online (Sandbox Code Playgroud)

I want to find out that the inputs of the addition are 6 and 4. Note how 6 never touches locals().

So far I could only come up with the opcode information, but I don't …

python cpython pdb

7
推荐指数
1
解决办法
144
查看次数

讲述一个函数如何收到一个参数?

我想知道在cpython中是否可以进行以下内省:

>>> def potato(x=69):
...     if x == 69 and ???:
...         print '69 was taken from argument defaults'
...     if x == 69 and ???:
...         print '69 was passed as positional arg'
...     if x == 69 and ???:
...         print '69 was passed as kwarg'
...
>>> potato()
69 was taken from argument defaults
>>> potato(69)
69 was passed as positional arg
>>> potato(x=69)
69 was passed as kwarg
Run Code Online (Sandbox Code Playgroud)

我对python2和python3的答案感兴趣,如果它们不同的话.

任何种类的Blackmagic涉及inspect,traceback,pdb, …

python debugging cpython

6
推荐指数
1
解决办法
108
查看次数

将 python 代码转换为共享对象

我想从 python 模块准备一个共享对象(.so)。我遇到了 Cython,它 a) 首先将 *.pyx 模块转换为 *.c 代码,b) 然后这个 *.c 代码将转换为共享对象 (.so)。Cython 的所有示例都说明了如何将这个 .so 导入到 python 中。

\n\n

但是,我有兴趣从 C 代码中读取这个共享对象。当我编写示例 C 代码来读取 .so 时,它会抛出一个错误,指出 .pyx 中实际存在的方法并不存在于 .so 对象中。

\n\n

我想知道 \na) 是否可以从不同的语言(例如 C)读取 Cython 的共享对象 \nb) 而且,如果上述语句为 True,我必须在代码中进行哪些更改,以便我将能够从 C 读取共享对象。

\n\n

谢谢,

\n\n

Python代码(保存为square_number.pyx)

\n\n
def square_me(int x):\n    return x * x\n
Run Code Online (Sandbox Code Playgroud)\n\n

Cython 对应的 setup.py 文件

\n\n
from distutils.core import setup\nfrom Cython.Build import cythonize\n\nsetup(\n    ext_modules=cythonize("square_number.pyx"),\n     )\n
Run Code Online (Sandbox Code Playgroud)\n\n

将上述 .pyx 转换为 .So 的命令行语句(通过 cython)

\n\n
python setup.py …
Run Code Online (Sandbox Code Playgroud)

c python cpython

6
推荐指数
1
解决办法
7078
查看次数