python如何区分“输入不完整”和“输入无效”?
有时,希望模仿Python交互式解释器的行为,在输入不完整时(例如,您键入了“if”语句的开头,或者没有关闭括号或三个字符串引号),给出一个延续提示,但当输入无效时,立即给出一条语法错误消息。
在Python中,您可以使用 codeop
模块,该模块非常接近解析器的行为。例如,IDLE就使用了这个。
在C中执行此操作的最简单方法是调用 PyRun_InteractiveLoop()
(可能在单独的线程中)并让Python解释器为您处理输入。您还可以设置 PyOS_ReadlineFunctionPointer()
指向您的自定义输入函数。有关更多提示,请参阅 Modules/readline.c
和 Parser/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