标签: cpython

Python这里不重用内存吗?Tracemalloc 的输出是什么意思?

我创建了一个包含一百万个对象的列表int,然后用其负值替换每个对象。tracemalloc报告 28 MB 额外内存(每个新int对象 28 字节)。为什么?intPython 不会为新对象重用垃圾收集对象的内存吗?或者我误解了tracemalloc结果?为什么会提到这些数字,它们的真正含义是什么?

\n
import tracemalloc\n\nxs = list(range(10**6))\ntracemalloc.start()\nfor i, x in enumerate(xs):\n    xs[i] = -x\nprint(tracemalloc.get_traced_memory())\n
Run Code Online (Sandbox Code Playgroud)\n

输出(在线尝试!):

\n
(27999860, 27999972)\n
Run Code Online (Sandbox Code Playgroud)\n

如果我替换xs[i] = -x为x = -x(因此新对象而不是原始对象被垃圾收集),则输出仅仅是(56, 196)(尝试一下)。我保留/丢失这两个物品中的哪一个有什么区别?

\n

如果我循环两次,它仍然只报告(27992860, 27999972)(尝试一下)。为什么不是 56MB?第二次运行与第一次运行有何不同?

\n

python memory cpython python-internals tracemalloc

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

为什么这个特定代码在 Python 3.11 中运行得更快?

我在一个名为 的 Python 文件中有以下代码benchmark.py:

source = """
for i in range(1000):
    a = len(str(i)) 
"""

import timeit

print(timeit.timeit(stmt=source, number=100000))
Run Code Online (Sandbox Code Playgroud)

当我尝试运行多个 python 版本时,我发现性能存在巨大差异。

C:\Users\Username\Desktop>py -3.10 benchmark.py
16.79652149998583

C:\Users\Username\Desktop>py -3.11 benchmark.py
10.92280820000451
Run Code Online (Sandbox Code Playgroud)

正如您所看到的,这段代码在 python 3.11 中运行得比以前的 Python 版本更快。我尝试反汇编字节码以了解此行为的原因,但我只能看到操作码名称的差异(CALL_FUNCTION被替换为PRECALL和CALL操作码)。

我很不确定这是否是性能变化的原因。所以我正在寻找一个参考 cpython 源代码来证明合理的答案。

python 3.11字节码:

  0           0 RESUME                   0

  2           2 PUSH_NULL
              4 LOAD_NAME                0 (range)
              6 LOAD_CONST               0 (1000)
              8 PRECALL                  1
             12 CALL                     1
             22 GET_ITER
        >>   24 FOR_ITER                22 …
Run Code Online (Sandbox Code Playgroud)

python performance cpython python-3.x python-3.11

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

在Python中使用long与int的性能影响

我需要在Python中操作适合64位的大数字.目前,我的代码在64位平台上运行,但是它必须在32位平台上运行的可能性很小但很明显.因此,我更愿意使用long类型来表示我的数字.我知道使用longover int类型会对性能产生影响.有多糟糕?我将对它们进行大量的除法和乘法运算,但结果也应该都适合64位.

python performance cpython

5
推荐指数
1
解决办法
797
查看次数

如何编写java库的python包装器

我们如何编写Python(CPython的带)绑定到一个Java库,使得想用这个Java库可以通过只写Python代码,不担心任何Java代码中使用它的开发者?

python java binding cpython word-wrap

5
推荐指数
1
解决办法
7378
查看次数

如何在CPython中实现字符串乘法?

Python允许整数乘以字符串:

>>> 'hello' * 5
'hellohellohellohellohello'
Run Code Online (Sandbox Code Playgroud)

如何在CPython中实现?

我特别感谢指向源代码的指针; Mercurial存储库是一个超出我导航能力的迷宫.

python string cpython multiplication

5
推荐指数
2
解决办法
867
查看次数

如何为IronPython访问包装C++代码

我有一个简单的例子,我想从Ironpython访问(我来自'常规/理智'python')所以我正在努力将我的C++代码导入Ironpython.通常我只是使用SWIG,包装我的代码,导入并继续我的快乐方式

但是,由于Ironpython是C#而不是C语言,这使得这个过程变得更加困难

我如何为ironpython包装这个类(我还为此示例附加了我的swig文件,但这可能没用)

#include "minimal.h"


double average(std::vector<int> v) {
    return std::accumulate(v.begin(), v.end(), 0.0) / v.size();
}

std::vector<double> half(const std::vector<double>& v) {
    std::vector<double> w(v);
    for (unsigned int i = 0; i<w.size(); i++)
        w[i] /= 2.0;
    return w;
}

void halve_in_place(std::vector<double>& v) {
    std::transform(v.begin(), v.end(), v.begin(),
        std::bind2nd(std::divides<double>(), 2.0));
}
Run Code Online (Sandbox Code Playgroud)

用头文件

#include <vector>
#include <algorithm>
#include <functional>
#include <numeric>

double average(std::vector<int> v);

std::vector<double> half(const std::vector<double>& v);

void halve_in_place(std::vector<double>& v);
Run Code Online (Sandbox Code Playgroud)

我有一个swig i文件minimal.i,但意识到有很多问题发出一个swig.exe -c ++ -python"%(FullPath)",并且铁蟒实际上在导入时接受它.

%module transfervector
%{
#include "minimal.h"
%}

%include "std_vector.i"
// …
Run Code Online (Sandbox Code Playgroud)

c++ python swig ironpython cpython

5
推荐指数
1
解决办法
416
查看次数

Py_None的值

我很清楚,这None用来表示缺乏价值.但由于在实现过程中所有内容都必须具有潜在价值,因此我希望看到使用了什么值来表示缺少值CPython.

我理解,根据文档,这NoneObject是一个单身人士.由于我的c技能是生锈的,我最好的,业余猜测,将是None指向为Py_None对象分配的内存的指针的值; 因为它是单身,这将保证唯一性.抑或是分配到c的NULL具有的价值0x0000基础上的第二个回答这个问题?

此外,文档还指出:

请注意,PyTypeObject for None不会直接在Python/C API中公开.

我猜这意味着你找不到它通过源搜索.(我做了,不知道在哪里看,object.c天真地相信我能理解任何东西)

但我不确定我对此的看法,所以我问道.

对象的c级别值是多少?Py_NoneCPython

c python cpython

5
推荐指数
1
解决办法
787
查看次数

修改locals()或frame.f_locals中的* existing *变量

我发现了与此问题相关的一些模糊的问题,但没有找到任何针对CPython的干净且特定的解决方案。我认为“有效”解决方案是特定于解释器的。

首先,我认为我了解:

  • locals() 给出了不可修改的字典。
  • 函数可以(并且确实确实)使用某种优化来访问其局部变量
  • frame.f_locals给出了locals()类似的字典,但不太容易通过hackhacking exec。或至少我没有能力做些骇人听闻的未证明的事情,例如locals()['var'] = value ; exec ""
  • exec 能够对局部变量做一些奇怪的事情,但它并不可靠-例如,我读到某处它在Python 3中不起作用。未经测试。

因此,我了解到,鉴于这些限制,向局部变量添加额外的变量永远是不安全的,因为这会破坏解释器的结构。

但是,应该可以更改已经存在的变量,不是吗?

我考虑过的事情

  • 在一种功能中f,可以访问f.func_code.co_nlocals和f.func_code.co_varnames。
  • 在一个框架中,可以通过访问/检查/读取变量frame.f_locals。这是通过设置跟踪器的用例sys.settrace。
  • 可以很容易地访问框架所在的功能-结合使用设置跟踪的用例,并使用它在给定触发器或任何给定局部变量的情况下“执行操作”。

变量应该在某个地方,最好是可写的...但是我找不到它。即使它是一个数组(用于有效的解释器访问),或者我需要一些额外的C特定接线,我也准备提交。

如何从跟踪函数或修饰的包装函数或类似的东西实现对变量的修改?

完整的解决方案当然会受到赞赏,但即使是某些指针也会对我有很大帮助,因为我在这里遇到了很多不可写的字典:-/


编辑:hackish的exec是做这样的事情这还是本

python cpython

5
推荐指数
2
解决办法
931
查看次数

PyImport_ImportModule,可以从内存加载模块吗?

我在我的C++程序中嵌入了python.

我使用PyImport_ImportModule来加载我在.py文件中编写的模块.但是如何从内存中加载它?假设我的.py文件是加密的,所以我需要先解密它并将代码提供给python来执行.

此外,如果我可以绕过/拦截或修改导入机制,那将是很好的,因此不会从文件系统加载模块,而是我自己的内存块,我该怎么做?

c++ python cpython python-embedding

5
推荐指数
1
解决办法
1223
查看次数

Python缓冲区,它们如何工作?

我正在调查Python缓冲区界面,看它是否有助于优化我的项目.我的项目处理大型二进制数据文件,这两个数据文件都占用了不可靠的内存以保留在内存中(当解压缩到Python数据结构时它们可以是多个gigs)并且需要花费太多时间来按需解压缩(20-30秒完全或迭代解压).相比之下,文件足够小(数十或数百兆)以二进制形式完全存储在内存中(或者必要时通过内存映射页面存储),并且结构化使得它们需要最少的解包来从例如C使用.

我一直在阅读有关缓冲区的一些内容,例如在PEP中,但有一些事情我不清楚使用它们以原生形式存储结构:

  1. 我知道缓冲区有关联的Struct样式格式定义,但是它们在访问时究竟在哪里转换为Python版本?Python是根据格式定义自动执行此操作,还是缓冲区导出器是通过getitem还是其他方式执行此操作?
  2. 使用缓冲区导出器存储大型C结构数组可以获得多少性能?例如迭代整个文件需要花费与使用Struct.unpack解压缩整个文件相同的时间,或者通过各种优化更有效(例如,如果您只是解压缩单个结构元素,如果您没有访问其他文件)在那个结构内)?
  3. 在元素访问期间是否可以对奇数数据类型进行自动转换?具体来说,这些文件格式中的一些喜欢使用奇长整数(例如5个字节长)以避免使用固定大小的较大整数类型.这可以透明有效地转换,或者在分配实际缓冲区以符合Struct定义时,我是否必须在导出器中将其转换为固定大小?

python cpython python-3.x

5
推荐指数
0
解决办法
102
查看次数