Hi,大家好,我是编程小6,很荣幸遇见你,我把这些年在开发过程中遇到的问题或想法写出来,今天说一说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>
int testcomplete(char *code)
/* code should end in
*/
/* return -1 for error, 0 for incomplete, 1 for complete */
{
node *n;
perrdetail e;
n = PyParser_ParseString(code, &_PyParser_Grammar,
Py_file_input, &e);
if (n == NULL) {
if (e.error == E_EOF)
return 0;
return -1;
}
PyNode_Free(n);
return 1;
}
另一个解决方案是尝试使用 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>
int main (int argc, char* argv[])
{
int i, j, done = 0; /* lengths of line, code */
char ps1[] = ">>> ";
char ps2[] = "... ";
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? */
else if (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);
}
来源:PY学习网:原文地址:https://www.py.cn/article.html