python如何区分“输入不完整”和“输入无效”?

python

有时,希望模仿Python交互式解释器的行为,在输入不完整时(例如,您键入了“if”语句的开头,或者没有关闭括号或三个字符串引号),给出一个延续提示,但当输入无效时,立即给出一条语法错误消息。

在Python中,您可以使用 codeop 模块,该模块非常接近解析器的行为。例如,IDLE就使用了这个。

在C中执行此操作的最简单方法是调用 PyRun_InteractiveLoop() (可能在单独的线程中)并让Python解释器为您处理输入。您还可以设置 PyOS_ReadlineFunctionPointer() 指向您的自定义输入函数。有关更多提示,请参阅 Modules/readline.cParser/myreadline.c

但是,有时必须在与其他应用程序相同的线程中运行嵌入式Python解释器,并且不能允许 PyRun_InteractiveLoop() 在等待用户输入时停止。那么另一个解决方案是调用 PyParser_ParseString() 并测试 e.error 等于 E_EOF ,如果等于,就意味着输入不完整。这是一个示例代码片段,未经测试,灵感来自Alex Farber的代码:

#define PY_SSIZE_T_CLEAN

#include<Python.h>

#include<node.h>

#include<errcode.h>

#include<grammar.h>

#include<parsetok.h>

#include<compile.h>

inttestcomplete(char*code)

/* code should end in

*/

/* return -1 for error, 0 for incomplete, 1 for complete */

{

node*n;

perrdetaile;

n=PyParser_ParseString(code,&_PyParser_Grammar,

Py_file_input,&e);

if(n==NULL){

if(e.error==E_EOF)

return0;

return-1;

}

PyNode_Free(n);

return1;

}

另一个解决方案是尝试使用 Py_CompileString() 编译接收到的字符串。如果编译时没有出现错误,请尝试通过调用 PyEval_EvalCode() 来执行返回的代码对象。否则,请将输入保存到以后。如果编译失败,找出是错误还是只需要更多的输入-从异常元组中提取消息字符串,并将其与字符串 “分析时意外的EOF” 进行比较。下面是使用GNUreadline库的完整示例(您可能希望在调用readline()时忽略 SIGINT ):

#include<stdio.h>

#include<readline.h>

#define PY_SSIZE_T_CLEAN

#include<Python.h>

#include<object.h>

#include<compile.h>

#include<eval.h>

intmain(intargc,char*argv[])

{

inti,j,done=0;/* lengths of line, code */

charps1[]=">>> ";

charps2[]="... ";

char*prompt=ps1;

char*msg,*line,*code=NULL;

PyObject*src,*glb,*loc;

PyObject*exc,*val,*trb,*obj,*dum;

Py_Initialize();

loc=PyDict_New();

glb=PyDict_New();

PyDict_SetItemString(glb,"__builtins__",PyEval_GetBuiltins());

while(!done)

{

line=readline(prompt);

if(NULL==line)/* Ctrl-D pressed */

{

done=1;

}

else

{

i=strlen(line);

if(i>0)

add_history(line);/* save non-empty lines */

if(NULL==code)/* nothing in code yet */

j=0;

else

j=strlen(code);

code=realloc(code,i+j+2);

if(NULL==code)/* out of memory */

exit(1);

if(0==j)/* code was empty, so */

code[0]="";/* keep strncat happy */

strncat(code,line,i);/* append line to code */

code[i+j]="

";/* append "

" to code */

code[i+j+1]="";

src=Py_CompileString(code,"<stdin>",Py_single_input);

if(NULL!=src)/* compiled just fine - */

{

if(ps1==prompt||/* ">>> " or */

"

"==code[i+j-1])/* "... " and double "

" */

{/* so execute it */

dum=PyEval_EvalCode(src,glb,loc);

Py_XDECREF(dum);

Py_XDECREF(src);

free(code);

code=NULL;

if(PyErr_Occurred())

PyErr_Print();

prompt=ps1;

}

}/* syntax error or E_EOF? */

elseif(PyErr_ExceptionMatches(PyExc_SyntaxError))

{

PyErr_Fetch(&exc,&val,&trb);/* clears exception! */

if(PyArg_ParseTuple(val,"sO",&msg,&obj)&&

!strcmp(msg,"unexpected EOF while parsing"))/* E_EOF */

{

Py_XDECREF(exc);

Py_XDECREF(val);

Py_XDECREF(trb);

prompt=ps2;

}

else/* some other syntax error */

{

PyErr_Restore(exc,val,trb);

PyErr_Print();

free(code);

code=NULL;

prompt=ps1;

}

}

else/* some non-syntax error */

{

PyErr_Print();

free(code);

code=NULL;

prompt=ps1;

}

free(line);

}

}

Py_XDECREF(glb);

Py_XDECREF(loc);

Py_Finalize();

exit(0);

}

以上是 python如何区分“输入不完整”和“输入无效”? 的全部内容, 来源链接: utcz.com/z/520559.html

回到顶部