《Python源码剖析》笔记 int_print()

在原书中,作者使用vs2003运行python2.5的项目,而现在配置这样的环境比较复杂,所以我尽量在配置环境上时间相差小一点,刚配置好,编译成功源文件,希望按照书上说的,修改int_print()函数,结果变化有点大,弄了很久才成功。

运行环境:
window10
vs2010
python2.7.13,编译的是PC目录里面的VS9.0的项目

先看看原书的写法:
在这里插入图片描述

而在python2.7中,这段代码变成了:

/* ARGSUSED */
static int
int_print(PyIntObject *v, FILE *fp, int flags)
     /* flags -- not used but required by interface */
{
	long int_val = v->ob_ival;  // *
    Py_BEGIN_ALLOW_THREADS  // *
    fprintf(fp, "%ld", int_val);
    Py_END_ALLOW_THREADS  // *
    return 0;
}

加*号注释的就是原书版本中没有的,这新添加的代码导致了很大的问题,下面的图片是没有改代码之前的运行结果:
没有改代码之前的运行结果
一开始,我直接把代码加到中间位置:

/* ARGSUSED */
static int
int_print(PyIntObject *v, FILE *fp, int flags)
     /* flags -- not used but required by interface */
{
	long int_val = v->ob_ival;
	Py_BEGIN_ALLOW_THREADS
	// ----------------------------------
	PyObject *myStr;
	myStr = PyString_FromString("I am int_print");
	PyObject_Print(myStr, stdout, 0); 
	printf("\n"); 
	// ----------------------------------
    fprintf(fp, "%ld", int_val);
    Py_END_ALLOW_THREADS
    return 0;
}

结果重新生成项目报错了
在这里插入图片描述
我以为是PyObject在这个版本里面换了名字,后来发现没有更换,然后在网上查了很久,发现有人说,应该在函数开头定义变量,于是我这样改:

/* ARGSUSED */
static int
int_print(PyIntObject *v, FILE *fp, int flags)
     /* flags -- not used but required by interface */
{
	long int_val = v->ob_ival;
	PyObject *myStr = NULL;  // 变量定义放到开头
	Py_BEGIN_ALLOW_THREADS
	// ----------------------------------
	myStr = PyString_FromString("I am int_print");
	PyObject_Print(myStr, stdout, 0); 
	printf("\n"); 
	// ----------------------------------
    fprintf(fp, "%ld", int_val);
    Py_END_ALLOW_THREADS
    return 0;
}

然后成功编译了,
在这里插入图片描述

就在我以为成功了的时候,执行生成的python文件,运行一开始的代码,发现报错了,
在这里插入图片描述
发生了一个关于PyEval_SaveThread的错误还和NULL有关,我以为是myStr变量不能赋值为NULL,去掉以后依然报错,重新研究发现PyEval_SaveThread这个应该和线程有关,但是这部分代码里面为什么会有线程出现呢?原来是Py_BEGIN_ALLOW_THREADS和Py_END_ALLOW_THREADS,这两行代码维护了一个线程,导致myStr在里面赋值,但是在外面定义,就会报错。
在这里插入图片描述
知道了这个原因,我就明白代码块应该放在线程代码的前面了

/* ARGSUSED */
static int
int_print(PyIntObject *v, FILE *fp, int flags)
     /* flags -- not used but required by interface */
{
	long int_val = v->ob_ival;
	PyObject *myStr = NULL;

	// ----------------------------------
	myStr = PyString_FromString("I am int_print");
	PyObject_Print(myStr, stdout, 0); 
	printf("\n"); 
	// ----------------------------------

	Py_BEGIN_ALLOW_THREADS
    fprintf(fp, "%ld", int_val);
    Py_END_ALLOW_THREADS
    return 0;
}

最后重新生成项目,运行python,结果输出成功!
在这里插入图片描述

总结:
通过今天的尝试,涡明白了在这个版本的python源代码中,变量要在开头先定义好;以及注意线程的问题。

PS.
如果编译项目的发现出现下面的错误:
在这里插入图片描述
那么说明你之前的Python打开以后忘记关掉了。

本人是C语言小白,没怎么接触过C语言,现在在研究Python源码,如果有什么错误,欢迎各位大佬指正,感谢!

评论 10
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值