得到错误引入Python脚本的一些包时问题,网页脚本错误怎么解决决

I'm trying to write a demo PAM module in C, which uses Embedding Python in C concept to run a script written in python (2.7), inside pam_sm_authenticate() function, which is written in C file (pam_auth.c).
This is the python script: test.py
import math
import numpy
def test_func():
a = "test"
The path for test.py is /usr/lib/Python2.7/ so that I can easily import it.
This is the C file:
#define PAM_SM_AUTH
#define PAM_SM_ACCOUNT
#define PAM_SM_SESSION
#include &security/pam_modules.h&
#include &security/_pam_macros.h&
#include &security/pam_appl.h&
#include&python2.7/Python.h&
#include&stdio.h&
#include&stdlib.h&
#include&string.h&
#define NOBODY "nobody"
/*PAM Stuffs*/
PAM_EXTERN int pam_sm_authenticate(
pam_handle_t* pamh, int flags, int argc, const char** argv)
const char *
user = NULL;
retval = pam_get_user(pamh, &user, NULL);
if(retval != PAM_SUCCESS)
fprintf(stderr, "%s", pam_strerror(pamh, retval));
return (retval);
fprintf(stdout, "retval= %d user=%s\n", retval,user);
if (user == NULL || *user =='\0')
pam_set_item(pamh, PAM_USER, (const char*)NOBODY);
/* Python Wrapper */
// Set PYTHONPATH TO working directory
//int res = setenv("PYTHONPATH",".",1);
//fprintf(stdout, "%d", res);
PyObject *pName, *pModule, *pDict, *pFunc, *pValue, *pR
// Initialize the Python Interpreter
Py_Initialize();
// Build the name object
pName = PyString_FromString((char*)"test");
// Load the module object
pModule = PyImport_Import(pName);
// pDict is a borrowed reference
PyErr_Print();
pDict = PyModule_GetDict(pModule);
// pFunc is also a borrowed reference
pFunc = PyDict_GetItemString(pDict, (char*)"test_func");
if (PyCallable_Check(pFunc))
pValue=NULL;
PyErr_Print();
pResult=PyObject_CallObject(pFunc,pValue);
PyErr_Print();
PyErr_Print();
printf("Result is %s\n",PyString_AsString(pResult));
// Clean up
Py_DECREF(pModule);
Py_DECREF(pName);/* */
// Finish the Python Interpreter
Py_Finalize();
return PAM_SUCCESS;
PAM_EXTERN int pam_sm_setcred(
pam_handle_t* pamh, int flags, int argc, const char** argv)
return PAM_SUCCESS;
PAM_EXTERN int pam_sm_acct_mgmt(
pam_handle_t* pamh, int flags, int argc, const char** argv)
return PAM_SUCCESS;
PAM_EXTERN int pam_sm_open_session(
pam_handle_t* pamh, int flags, int argc, const char** argv)
return PAM_SUCCESS;
PAM_EXTERN int pam_sm_close_session(
pam_handle_t* pamh, int flags, int argc, const char** argv)
return PAM_SUCCESS;
PAM_EXTERN int pam_sm_chauthtok(
pam_handle_t* pamh, int flags, int argc, const char** argv)
return PAM_SUCCESS;
The C-file is just a modification of pam_permit.c. The C file is compiled using gcc ( gcc -shared -o pam_auth.so -fPIC
pam_auth.c -I/usr/include/python2.7 -lpython2.7 ) to obtain an .so file (pam_auth.so) and is put inside the folder /lib/security/
I changed the PAM configuration of 'sudo' file in /etc/pam.d as follows:
pam_env.so readenv=1 user_readenv=0
pam_env.so readenv=1 envfile=/etc/default/locale user_readenv=0
#@include common-auth #this line is commented to make it use my pam module
pam_auth.so
@include common-account
@include common-session-noninteractive
The line "auth
pam_auth.so" forces the system to use my module for authentication everytime I use the command "sudo". (for ex- sudo nautilus)
Now the problem is:
This line in C file " pModule = PyImport_Import(pName); " gives an import error, which is printed by PyErr_Print() as follows:
stitches@Andromida:~$ sudo nautilus
retval= 0 user=stitches
Traceback (most recent call last):
File "/usr/lib/python2.7/subho_auth.py", line 8, in &module&
import numpy
File "/usr/lib/python2.7/dist-packages/numpy/__init__.py", line 153, in &module&
from . import add_newdocs
File "/usr/lib/python2.7/dist-packages/numpy/add_newdocs.py", line 13, in &module&
from numpy.lib import add_newdoc
File "/usr/lib/python2.7/dist-packages/numpy/lib/__init__.py", line 8, in &module&
from .type_check import *
File "/usr/lib/python2.7/dist-packages/numpy/lib/type_check.py", line 11, in &module&
import numpy.core.numeric as _nx
File "/usr/lib/python2.7/dist-packages/numpy/core/__init__.py", line 6, in &module&
from . import multiarray
ImportError: /usr/lib/python2.7/dist-packages/numpy/core/multiarray.so: undefined symbol: PyExc_SystemError
Segmentation fault (core dumped)
As per I can understand,it fails to import numpy library as specified in test.py file. How to solve this problem of ImportError & PyExc_SystemError?
The python script works as charm if I run in as follows:
#include &Python.h&
#include &stdlib.h&
#include &string.h&
int main()
// Set PYTHONPATH TO working directory
//int res = setenv("PYTHONPATH",".",1);
//fprintf(stdout, "%d", res);
PyObject *pName, *pModule, *pDict, *pFunc, *pValue, *pR
// Initialize the Python Interpreter
Py_Initialize();
// Build the name object
pName = PyString_FromString((char*)"test");
// Load the module object
pModule = PyImport_Import(pName);
// pDict is a borrowed reference
PyErr_Print();
pDict = PyModule_GetDict(pModule);
// pFunc is also a borrowed reference
pFunc = PyDict_GetItemString(pDict, (char*)"test_func");
if (PyCallable_Check(pFunc))
pValue=NULL;
PyErr_Print();
pResult=PyObject_CallObject(pFunc,pValue);
PyErr_Print();
PyErr_Print();
printf("Result is %s\n",PyString_AsString(pResult));
// Clean up
Py_DECREF(pModule);
Py_DECREF(pName);/* */
// Finish the Python Interpreter
Py_Finalize();
If it works under general python embedding examples, why its not working in PAM-based embedding examples (where .so files are used)?
PS: I'm importing numpy for a particular reason. Don't ask why I've not used in anywhere in python script as this is just a demo script of what I'm trying to achieve. Moreover, import math doesn't give any import error. I get import error for SciPY too.
PPS: Numpy and Scipy packages works perfect in python scripts and is installed under /usr/lib/python2.7/dist-packages/. I'm using ubuntu 14.04.
Please help!!!!
解决方案 I don't know the answer to your question, but I am wondering why it didn't fail earlier.
The host application does not know your PAM module will be needed using libpython2.7.so.1, so somehow that must being loaded dynamically otherwise the Py_Initialize() call would fail with the same error.
Given you say it doesn't fail there it must be loaded.
However from the error you are getting we can deduce the symbols it contains (such as PyExc_SystemError) are not visible to dynamic libraries subsequently loaded.
This is the default when libraries are loaded using dlopen() (see RTLD_LOCAL in man 3 dlopen).
To override it, you must pass RTLD_GLOBAL to dlopen().
Maybe that's your problem.
Other comments about your code:
Calling Py_Initialise() for each pm_sm_...() call is going to be expensive and possibly surprising to the python modules.
It means all data the python module accumulated within one call
(like say voice or the user name) will be discarded when the next call is made.
You are better off loading libpython2.7.so.1 and initialising PAM once, then using the cleanup function of pam_set_data() to unload it when you are done.
In a related issue, your PAM module isn't usable from Python programs because you always call Py_Initialise() (and I presume the matching call to Py_Finalize()).
If you program hadn't fallen over where it did, it would have fallen over on the line printf("Result is %s\n",PyString_AsString(pResult)) because pResult isn't initialised.
As I think you know, all the boilerplate you have here to let you wring PAM modules in Python is provided by
- no C required.
Since you are evidently writing your PAM module in Python anyway, you are already exposed to the overheads it incurs but are missing out on the features it provides like logging uncaught Python exceptions.
And most importantly, using it means you can avoid C entirely.
Your PAM module will be loaded into programs that guard the security of the machine - programs like login, sudo, and xdm/gdm3.
Avoiding C means also avoiding the legions of security bugs C programs can have that are impossible in Python - buffer overruns, uninitialised pointers and accessing free'ed memory.
Since you have one of those bugs in your the C code you posted here, avoiding it sounds like a good idea.
本文地址: &
我想用C编写的演示PAM模块,它采用Python嵌入在C概念来运行Python编写的(2.7)的脚本,里面的pam_sm_authenticate()函数,这是写在C文件(pam_auth.c )。这是Python脚本:test.py
进口数学进口numpy的高清test_func():
A =“测试”
返回 有关test.py的路径/usr/lib/Python2.7/这样我就可以轻松地将其导入。这是C文件: 的#define PAM_SM_AUTH#定义PAM_SM_ACCOUNT#定义PAM_SM_SESSION#包括LT&;安全/ pam_modules.h>#包括LT&;安全/ _pam_macros.h>#包括LT&;安全/ pam_appl.h>#包括LT&; python2.7 / Python.h>#包括LT&;&stdio.h中GT;#包括LT&;&stdlib.h中GT;#包括LT&;&string.h中GT;#定义NOBODY“没有人”/ * PAM的东西* /PAM_EXTERN INT的pam_sm_authenticate(
pam_handle_t * pamh表示,INT标志,INT ARGC,为const char ** argv的){
为const char *用户;
INT RETVAL;
用户= NULL;
RETVAL = pam_get_user(pamh表示,&放大器;用户,NULL);
如果(RETVAL!= PAM_SUCCESS)
fprintf中(标准错误,“%S”,pam_strerror(pamh表示,RETVAL));//回报(RETVAL);
fprintf中(标准输出,“RETVAL =%d个用户=%s的\\ n”,RETVAL,用户);
如果(用户== NULL || *用户=='\\ 0')
pam_set_item(pamh表示,PAM_USER,(为const char *)NOBODY);
/ * Python包装* /
//设置PYTHONPATH工作目录
// INT解析度= SETENV(“PYTHONPATH”,1“。”);
// fprintf中(标准输出,“%D”,RES);
*的PyObject PNAME,* pModule,* pDict,* pFunc,* P值,*
//初始化Python的国米preTER
Py_Initialize();
//构建名称对象
PNAME = PyString_FromString((字符*)“测试”);
//加载模块对象
pModule = PyImport_Import(PNAME);
// pDict是借来参考
PyErr_Print();
pDict = PyModule_GetDict(pModule);
// pFunc也是借来参考
pFunc = PyDict_GetItemString(pDict,(字符*)“test_func”);
如果(PyCallable_Check(pFunc))
P值= NULL;
PyErr_Print();
presult = PyObject_CallObject(pFunc,P值);
PyErr_Print();
PyErr_Print();
的printf(“结果为%s \\ n”,PyString_AsString(presult));
Py_DECREF(pModule);
Py_DECREF(PNAME); / * * /
//完成Python的国米preTER
Py_Finalize();
返回PAM_SUCCESS;}PAM_EXTERN INT pam_sm_setcred(
pam_handle_t * pamh表示,INT标志,INT ARGC,为const char ** argv的){
返回PAM_SUCCESS;}PAM_EXTERN INT pam_sm_acct_mgmt(
pam_handle_t * pamh表示,INT标志,INT ARGC,为const char ** argv的){
返回PAM_SUCCESS;}PAM_EXTERN INT pam_sm_open_session(
pam_handle_t * pamh表示,INT标志,INT ARGC,为const char ** argv的){
返回PAM_SUCCESS;}PAM_EXTERN INT pam_sm_close_session(
pam_handle_t * pamh表示,INT标志,INT ARGC,为const char ** argv的){
返回PAM_SUCCESS;}PAM_EXTERN INT pam_sm_chauthtok(
pam_handle_t * pamh表示,INT标志,INT ARGC,为const char ** argv的){
返回PAM_SUCCESS;} 在C-文件只是一个pam_permit.c的修改。 C文件是使用gcc编译(GCC -shared -o pam_auth.so -fPIC pam_auth.c -I / usr / include目录/ python2.7 -lpython2.7),以获得.so文件(pam_auth.so),并放文件夹/ lib目录内/安全/ 我改变了'须藤'文件中的PAM配置/etc/pam.d中如下: #%PAM-1.0需要AUTH pam_env.so readenv = 1 user_readenv = 0AUTH需要pam_env.so readenv = 1 envfile =在/ etc /默认/区域设置user_readenv = 0#@包括普通-auth的#此行被注释,以使它使用我的PAM模块AUTH需要pam_auth.so@include共同账户@include共会话非交互式 行“pam_auth.so需要身份验证”强制系统使用我的模块我用命令“命令”验证每次。 (为前须藤鹦鹉螺)现在的问题是:;这条线在C文件“pModule = PyImport_Import(PNAME)”,如下所示给出了一个导入错误,这是由PyErr_Print()打印的: 拆线@ Andromida:?$ sudo的鹦鹉螺RETVAL = 0 USER =针回溯(最近通话最后一个):
文件“/usr/lib/python2.7/subho_auth.py”,8号线,上述&&模块GT;
进口numpy的
文件“/usr/lib/python2.7/dist-packages/numpy/__init__.py”,153行,上述&&模块GT;
从。进口add_newdocs
文件“/usr/lib/python2.7/dist-packages/numpy/add_newdocs.py”,13号线,上述&&模块GT;
从numpy.lib进口add_newdoc
文件“/usr/lib/python2.7/dist-packages/numpy/lib/__init__.py”,8号线,上述&&模块GT;
从.type_check进口*
文件“/usr/lib/python2.7/dist-packages/numpy/lib/type_check.py”,第11行,上述&模块>
进口numpy.core.numeric作为_nx
文件“/usr/lib/python2.7/dist-packages/numpy/core/__init__.py”,第6行,上述&模块>
从。进口多阵列导入错误:/usr/lib/python2.7/dist-packages/numpy/core/multiarray.so:未定义的符号:PyExc_SystemError分段错误(核心转储) 根据我可以理解,但没有按test.py文件中指定导入numpy的图书馆。如何解决导入错误和放这个问题; PyExc_SystemError? Python脚本工作方式的魅力,如果我运行如下: 的#include< Python.h>#包括LT&;&stdlib.h中GT;#包括LT&;&string.h中GT;诠释的main(){
//设置PYTHONPATH工作目录
// INT解析度= SETENV(“PYTHONPATH”,1“。”);
// fprintf中(标准输出,“%D”,RES);
*的PyObject PNAME,* pModule,* pDict,* pFunc,* P值,*
//初始化Python的国米preTER
Py_Initialize();
//构建名称对象
PNAME = PyString_FromString((字符*)“测试”);
//加载模块对象
pModule = PyImport_Import(PNAME);
// pDict是借来参考
PyErr_Print();
pDict = PyModule_GetDict(pModule);
// pFunc也是借来参考
pFunc = PyDict_GetItemString(pDict,(字符*)“test_func”);
如果(PyCallable_Check(pFunc))
P值= NULL;
PyErr_Print();
presult = PyObject_CallObject(pFunc,P值);
PyErr_Print();
PyErr_Print();
的printf(“结果为%s \\ n”,PyString_AsString(presult));
Py_DECREF(pModule);
Py_DECREF(PNAME); / * * /
//完成Python的国米preTER
Py_Finalize();
返回0;} 如果它工作在一般蟒蛇嵌入的例子,为什么它在基于PAM嵌入的例子不工作(其中.so文件被使用)? PS:我导入numpy的特定原因。不要问我为什么还没有在python脚本的任何地方作为这仅仅是我想要达到一个演示脚本。此外,进口数学不给任何导入错误。我得到的进口错误SciPy的了。
PPS:numpy的和SciPy的包完美的作品在Python脚本和下/usr/lib/python2.7/dist-packages/安装。我使用Ubuntu 14.04。请帮助!解决方案 我不知道回答你的问题,但我想知道为什么没有更早失败。主机应用程序不知道你的PAM模块将使用libpython2.7.so.1需要,所以在某种程度上必须被动态加载,否则Py_Initialize()调用将失败,并同样的错误。由于你说它不会失败有它必须被加载。但是从错误中你得到我们可以推断出它包含的符号(如 PyExc_SystemError 的)不是随后加载动态库可见。这是默认的库时使用装载的的dlopen()的(见的 RTLD_LOCAL 的中的男子3的dlopen 的)。要覆盖它,你必须通过的 RTLD_GLOBAL 导入的的dlopen()的。也许这就是你的问题。你的code。其他的评论: 调用Py_Initialise()每个pm_sm _...()调用将是昂贵的,可能令人惊讶的Python模块。这意味着Python模块积累的一个呼叫中的所有数据(如说语音或用户名)下一个调用时将被丢弃。你最好装libpython2.7.so.1和初始化PAM一次,然后使用pam_set_data的清理功能()来卸载它,当你做。
在一个相关的问题,您的PAM模块是不是从Python程序使用,因为你总是调用的 Py_Initialise()的(我presume匹配调用的 Py_Finalize ()的)。
如果你的程序没有超过它在哪里倒下,就已经下跌了就行的的printf(“结果为%s \\ n”,PyString_AsString(presult)),因为 presult 的未初始化。
当我想你知道,你在这里的样板,让你拧在Python PAM模块是通过的
- 没有C需要。既然你显然用Python编写的PAM模块,无论如何,你已经接触到它即被但它提供了诸如记录未捕获的Python的异常功能丢失了开销。而最重要的是,使用它意味着你可以避开时完全是。您的PAM模块将被加载到守卫机器的安全程序 - 像登录,须藤和XDM / gdm3程序。避免C表示还避免安全漏洞C程序可以有在Python是不可能的军团 - 缓冲区溢出,未初始化的指针和访问free'ed内存。既然你有这些错误的一个在你的C code您张贴在这里,以避免这听起来像一个好主意。
本文地址: &
扫一扫关注官方微信您所在位置: &
&nbsp&&nbsp&nbsp&&nbsp
python函脚本入门学习经典手册.doc75页
本文档一共被下载:
次 ,您可全文免费在线阅读后下载本文档。
文档加载中...广告还剩秒
需要金币:200 &&
python函脚本入门学习经典手册
你可能关注的文档:
··········
··········
Python脚本使用详解
写在前面的话 2
一、Python语言基础 3
1数学运算符 3
2字符串操作 4
3模块的使用(Modules) 5
4使用def构建函数 6
5流程控制结构:If,While,For 6
6简单输入和输出 9
二、ArcGIS&Python 10
1如何创建地理处理对象(geoprocessor object) 10
2获取地理处理帮助 10
2.1举例:如何使用Geoprocessor Programming Model中的Lists 11
3使用地理处理工具――Toolboxes和Aliases 11
4在建模中使用脚本(Scripts in ModelBuilder) 12
5 在PythonWin里调试地理处理脚本 18
5.1 调试选择和消息 19
5.2PythonWin的调试工具 20
5.3地理处理工具举例 21
6使用描述(Describe)和存在(Exists)获取数据信息 21
6.1描述 22
6.2存在(Exists) 23
6.3在循环中使用描述和存在 23
7在Python脚本中使用地图代数(Map Algebra) 26
8数据管理和指针(Data Management and Cursors) 27
8.1数据管理(Data Management) 27
8.2指针(Cursors) 28
附录1:地理处理脚本中输入&输出方法指南 31
附录2:其他 32
写在前面的话
一直想学习ArcGIS中的Python脚本,大四下半学期终于有了时间,可是想找到这么一本好的教材不容易。茫茫互联网,终于找到了旧金山州立大学Jerry Davis教授的个人主页,对其中《Geoprocessing Scripts With Python》如获至宝,独乐乐不如众乐乐,现在将其教程翻译并结合自己的学习情况给出总结。希望能够给更多想学习Python的同学一个参考。
另外,在我刚开始接触Python时,是看了台湾辅仁大学一位老师的视频课件,在此致谢。
我想从两个大部分总结:一、Python语言基础;二、ArcGIS&Python。其中第一部分参考了《Python精要参考(第二版)》、《Python编程金典(读书笔记)》等书籍文献。对于多数读者来说,可能或多或少有一些编程基础,所以理解起来应该
正在加载中,请稍后...ArcGIS Python编程案例(12)-异常和错误处理 - 简书
ArcGIS Python编程案例(12)-异常和错误处理
我们将在本章介绍以下案例:
查看Python默认的错误消息
添加Python异常处理语句结构(try/except/finally)
调用GetMessages()函数获取工具消息
使用严重性级别筛选工具消息
调用GetMessage()返回单个消息
测试并响应特定错误消息
ArcGIS地理处理工具和函数执行过程中会返回不同的消息。这些消息包括信息性消息,也可能含有提示警告信息或错误状况,这些警告或错误的出现意味着工具执行完毕后没有出现预期的结果或工具执行完全失败。不过这些消息并不是以消息框的形式显示,你需要调用许多不同的ArcPy函数来访问这些消息。到目前为止,我们都忽略了这些消息、提醒和错误。主要是因为希望你能专注于学习一些基本的概念,而没有增加额外的代码复杂度,而这些消息有关的代码对于创建能够处理错误状况的地理处理脚本是非常有必要的。现在是时候来学习如何在Python中创建异常处理语句结构。这些脚本可以处理在脚本执行过程中生成的提示警告信息,错误信息和通用信息。这些异常处理语句会让你的脚本更加灵活而且更不容易出现错误。你已经使用了基本的try和except语句块来执行一些简单的错误处理操作。在本章中,我们会介绍更多关于异常处理语句的细节内容。
查看Python默认的错误消息
默认情况下,Python在脚本中一旦遇到问题就会生成错误消息。这些错误消息的内容对于运行脚本的最终用户来讲并非总是那么明确具体。尽管如此,查看这些原始消息还是很有价值的。在后面的案例中,我们会使用Python错误处理语句结构来了解错误信息以及能够在必要时针对错误和异常情况作出反馈。
Getting ready
本案例中,我们会创建并运行一个有错误的脚本。在脚本中我们不会添加任何地理处理或Python异常处理结构。这样我们就能够看到Python自身返回的错误消息。
How to do it...
按照以下步骤来查看Python自身生成的错误消息,该消息是由于工具在执行过程中遇到错误生成的:1.打开IDLE,创建一个新的脚本。2.脚本保存为C:\ArcpyBook\Ch12\ErrorHandling.py文件。3.导入arcpy模块:
import arcpy
4.设置工作空间路径:
arcpy.env.worksapce = "C:/ArcpyBook/data"
5.调用Buffer工具。Buffer工具需要一个缓冲距离作为其中一个参数。在代码中我们故意舍掉距离参数:
arcpy.Buffer_analysis("Streams.shp","Streams_Buff.shp")
6.运行脚本。你会看到如下结果显示:
Traceback (most recent call last):
File "&string&", line 3, in &module&
arcpy.Buffer_analysis("Streams.shp","Stream_buffer.shp")
File "c:\program files\(x86)\arcgis\desktop10.1\arcpy\arcpy\analysis.py", line 687, in Buffer
ExecuteError: Failed to execute. Parameters are not valid.
ERROR 000735: Distance [value or field]: Value is required
Failed to execute (Buffer).
How it works...
输出的错误消息中的内容似乎没什么有用的信息。如果是一个有经验的程序员,通常能够找到问题在于我们没有提供缓冲距离参数。然而,很多情况下,返回的错误消息并不会给你解决问题提供很多帮助信息。代码错误在编程中是不可避免的。如何理解这些称为异常的错误是非常重要的。你可以使用Python异常处理语句结构来有步骤地处理这些错误,而这些语句结构会查看arcpy生成的异常信息并作出相对应的反馈。如果缺少这些语句结构,脚本在执行过程中很可能会随时中断或失败,从而让最终用户懊恼。
添加Python异常处理结构(try/except/finally)
Python内置的异常处理语句结构能够捕获脚本执行中生成的错误消息。你可以利用这些错误信息为最终用户提供一个更为明确的消息内容并在必要时候作出反馈。
Getting ready
异常是代码中的非正常或错误状况。异常处理语句能够捕获并处理代码中的错误,可以让程序能够从错误状况中恢复。除了用来处理错误,异常处理语句还可用于其他方面,比如事件提醒和特殊情况处理等。Python的异常有两种发生方式。异常既可以捕获也可以触发。代码中发生错误时,Python会自动触发一个异常,这类异常有可能会在代码中处理。作为一名程序员需要捕获自动触发的异常。异常还可以通过代码方式进行人工触发。这种情况下,你需要提供一个异常处理机制来捕获这类人工触发的异常。你可以使用raise语句来实现触发异常。try/except语句是Python中用来处理异常的一组完整的组合语句。try语句结构是以try作为首行代码,后面紧跟一组缩进的语句块,之后是一个或多个可选的except语句用来命名捕获的异常,最后是一个可选的else语句和finally语句。下面以try/except/else语句结构来说明运行机制。在try语句中,Python就会知道你现在正处于一个try语句块中,一旦有异常发生就会直接交给后面的except语句进行处理。try语句块中的每一行代码都会执行。假如没有异常发生,代码就会跳至else语句来执行else语句中的代码然后再执行整个try/except/else语句块后面的代码。如果有异常发生,Python会查找相匹配的异常语句,如果找到了匹配的except语句,那么就会执行该except语句中的代码,之后执行整个try/except/else语句块后面的代码。在这种情况下else语句则不会执行。如果没有找到匹配的except语句,那么在这种情况下,异常提交给最高层try语句中。这将导致一个无法处理的异常,也就会遇到我们在本章第一个案例中看到的错误消息。本案例中,我们会添加一些基本的Python异常处理结构语句。在本案例中,我们先介绍一个非常简单的try/except语句结构。
How to do it...
按照以下步骤在脚本中添加Python错误处理语句:1.在IDLE中打开C:\ArcpyBook\Ch12\ErrorHandling.py文件。2.在脚本中添加try/except语句:
import arcpy
arcpy.env.workspace = "C:/ArcpyBook/data"
arcpy.Buffer_analysis("Streams.shp","Streams_Buff.shp")
print "Error"
3.保存并修改脚本。你会看到一条简答的消息显示Error。这条信息没有比我们在第一个案例中见到的结果更有帮助。事实上该消息的有用信息更少。本案例的目的只是介绍try/except语句结构。
How it works...
这是一个非常简单的结构。try语句块中的所有语句都会执行。如果异常发生,语句会跳至except部分来打印错误消息,在本案例中也就是一个简单的Error消息。如我之前所说,尽管这种消息对用户难言有价值,但希望可以让你对try/except语句的工作方式有个基本了解,同时作为一名程序员,你需要更好地了解程序反馈的任何错误。在下一个案例中,你会学习如何在异常处理结构中获取由地理处理工具生成的消息。
There's more...
另外一种try语句类型是try/finally语句,该语句可用于执行终止操作。当finally语句出现在try语句块中使,无论是否发生异常或错误,finally语句部分在最后都会执行。如果有异常发生,Python会执行try语句块,之后执行finally语句块,然后接着执行整个try语句后面的代码。如果执行过程中没有出现异常,Python会执行try语句块,之后执行finally语句块。不管错误是否发生都需要确保执行某项操作时候,finally语句会非常有用。
调用GetMessages()获取工具消息
ArcPy提供的GetMessages()函数用于获取ArcGIS工具执行过程中生成的消息。这些消息既包括像工具执行的起始时间这样的信息性消息,也包括由于未得到预期结果或工具执行失败生成的警告信息和错误信息。
Getting ready
工具执行过程中会生成各种各样的消息。这些消息包括消息性消息,比如工具执行的开始和结束时间,工具使用的参数值以及进度消息。除此之外,工具还会生成警告消息和错误消息。这些消息可以通过Python脚本来读取,同时还可以编写代码来处理出现的警告或错误消息。ArcPy会保存上一次执行的工具生成的消息,你可以调用GetMessages()函数来读取这些消息,GetMessages()会返回一个包含了工具在上一次执行中生成的所有消息的字符串。你可以使用严重性参数来筛选字符串以返回像警告消息或错误消息这样特定类型的消息。第一条消息通常是工具的名称,最后一条信息是工具执行的开始和结束时间。在本案例中,你会添加一行except语句,该语句用来打印关于当前运行工具执行过程中具体消息。
How to do it...
按照以下步骤来学习如何添加GetMessages()函数来生成工具执行返回的消息列表。1.在IDLE中打开C:\ArcpyBook\Ch12\ErrorHandling.py文件。2.添加GetMessages()函数:
import arcpy
arcpy.env.workspace = "C:/ArcpyBook/data"
arcpy.Buffer_analysis("Streams.shp","Streams_Buff.shp")
print arcpy.GetMessages()
3.保存并运行脚本。这一次返回的错误消息应该会更为具体。你会注意到还有其他类型的消息返回,比如脚本执行的开始和结束的时间等。
Executing: Buffer c:/ArcpyBook/data\Streams.shp c:/ArcpyBook/data\Streams_Buff.shp # FULL ROUND NONE #
Start Time: Tue Nov 13 22:23:04 2012
Failed to execute. Parameters are not valid.
ERROR 000735: Distance [value or field]: Value is required
Failed to execute (Buffer).
Failed at Tue Nov 13 22:23:04 2012 (Elapsed Time: 0.00 seconds)
How it works...
GetMessages()函数返回上一次执行工具过程中生成的所有的消息。这里需要要强调的是该函数仅返回上一次执行的工具生成的消息。如果脚本中有多个工具执行的话那就需要留意这一点。历史记录中执行的工具过程生成的消息不能通过该函数获取。不过,你可以使用Result对象获取历史记录中工具运行的信息。
使用严重性级别筛选工具消息
如前面提到的那样,所有的工具生成的消息可以分为消息性消息,警告消息和错误消息。GetMessages()函数可接受一个严重性级别参数用来筛选返回的消息。举个例子,你可能只对工具执行过程中生成的错误消息感兴趣,对消息性消息和警告信息不感兴趣。调用GetMessages(2)语句返回的消息中就仅包含错误消息。
Getting ready
任何消息都可以被归类到三种消息类型中一类中,消息类型可以通过一个严重性级别来指定。信息性消息(Informational messages)提供与工具执行有关的描述性信息,比如工具执行进度,工具执行的开始和结束时间,输出数据特征等等。消息性消息的严重性级别用数字0来表示。警告消息(Warning messages)表示工具执行过程中出现的问题可能影响输出结果的时候生成。警告信息的严重性级别用数字1表示,同时并不会中止正在执行的工具。最后一个类型是错误消息(error messages),该类型消息的严重性级别实用数字2表示。错误消息表示有严重事件阻止工具运行。工具执行过程中会生成多个消息,这些消息都保存在列表中。更多关于消息严重性的信息见下图。在本案例中,你将学习如何调用GetMessages()函数来筛选工具生成的消息。
How to do it...
筛选工具返回的消息非常简单。你只要将想要返回的严重性级别相对应的数字作为参数提供给GetMessages()函数即可。1.在IDLE中打开C:\ArcpyBook\Ch12\ErrorHandling.py文件。2.将数值2最为参数传递给GetMessages()函数:
import arcpy
arcpy.env.workspace = "C:/ArcpyBook/data"
arcpy.Buffer_analysis("Streams.shp","Streams_Buff.shp")
print arcpy.GetMessages(2)
3.保存并运行脚本会看到如下结果:
Failed to execute. Parameters are not valid.
ERROR 000735: Distance [value or field]: Value is required
Failed to execute (Buffer).
How it works...
如前所述,GetMessages()函数可接受0,1,2整数值参数。数值0表示返回消息性消息,而数值1表示返回警告消息。在本案例中,我们使用数值2表示我们只关注错误消息。这样你在输出结果中就不会看到脚本执行的开始和结束时间这样的信息性消息。
测试并响应特定错误消息
所有的错误和警告都会生成一个特定的错误代码。我们可以在脚本中来检查特定的错误代码,并基于这些错误代码来执行特定的操作。
Getting ready
地理处理工具的返回的错误和警告都包含一个六位数字代码和一条描述性信息。你在脚本中可以检测特定的错误代码并作出相应地反馈。你可以在ArcGIS帮助系统中的地理处理|工具错误和警告(Geoprocessing|Tool errors and warnings)中看到包含所有错误消息和代码的列表。如下图所示,所有的错误根据错误代码都有一个对应的描述页面:
How to do it...
按照以下步骤来学习如何编写代码来响应地理处理工具执行过程中生成的特定的错误代码:1.点击开始|所有程序|ArcGIS|ArcGIS Desktop 10帮助(Start|Programs|ArcGIS|ArcGIS for Desktop Help)打开帮助系统。2.找到地理处理|工具错误和警告|工具错误1-10000|工具错误和警告:701-800(Geoprocessing|Tool errors and warnings|Tool errors 1-10000|Tool errors and warning:701-800)。3.选择000735:&值&:需要值(000735:&value&:value is required)。该错误提示没有提供工具需要的必选参数。我们在脚本中没有提供缓冲距离参数导致了错误消息产生,其中包括了我们在帮助系统中看到的错误代码(000735)。下面的消息代码中,你会发现完整的错误消息文本。留意错误代码(000735)。
ERROR000735:Distance[value or field]:Value is required
4.在IDLE中打开C:\ArcpyBook\Ch12\ErrorHandling.py文件。5.如下所示修改脚本代码:
print "Error found in Buffer tool \n"
errCode = arcpy.GetReturnCode(3)
if "735" in str(errCode):
print "Distance value not provided \n"
print "Running the buffer again with a default value \n"
defaultDistance = "100 Feet"
arcpy.Buffer_analysis("Steams.shp","Streams_Buff.shp",defaultDistance)
print "Buffer complete"
6.保存并运行代码。你会看到如下消息:
Error found in Buffer tool
Distance value not provided for buffer
Running the buffer again with a default distance value
Buffer complete
How it works...
我们在代码中调用了arcpy.GetReturnCode()函数来返回工具生成的错误代码。之后if语句用来检测错误代码中是否包含数值735,该代码表示错误是由于没有提供工具必选参数造成。接下来我们提供了一个缓冲距离值并再次调用Buffer工具。
调用GetMessage()函数返回单个消息
GetMessages()会返回上一次工具运行时生成的全部消息列表,不过你可以调用GetMessage()函数来获取其中的单个消息。
Getting ready
到目前为止,我们都是返回工具生成的全部消息。不过,你可以调用GetMessage()函数为用户返回单个消息,该函数接受一个整型参数来指定要返回的特定消息。工具生成的消息都是位于消息列表或数组中。这里提醒一下,列表是零值开始计算索引值的,也就意味着了列表中的第一个元素的位置为0。比如,GetMessage(0)会返回列表中的第一条信息,而GetMessage(1)则返回第二条信息。第一条消息通常是当前运行的工具名称以及参数信息。第二条消息返回脚本运行的开始时间,而最后一条消息则返回脚本的结束时间。
How to do it...
1.在IDLE中打开C:\ArcpyBook\Ch12\ErrorHandling.py文件。2.如下所示修改代码:
import arcpy
arcpy.env.workspace = "C:/ArcpyBook/data"
arcpy.Buffer_analysis("Streams.shp","Streams_Buff.shp")
print arcpy.GetMessage(1)
print arcpy.GetMessage(arcpy.GetMessageCount()-1)
3.保存并运行脚本,你会看到如下结果显示:
Start Time: Wed Nov 14 09:07:35 2012
Failed at Wed Nov 14 09:07:35 2012 (Elapsed Time: 0.00 seconds)
How it works...
我们之前没有介绍GetMessageCount()函数。该函数返回工具生成的消息数量。记住消息列表是从零值开始索引,因此我们需要从GetMessageCount()返回的结果中减去1来获取列表中的最后一条消息。否则的话,我们就是在试图访问列表中不存在的消息。在本案例中,我们获取了脚本执行的开始和结束时间。第二条消息通常是脚本执行的开始时间,而最后一条消息则是脚本执行的结束时间。下面的返回结果中则说明了这个问题:
Message 0 - Executing: Buffer c:/ArcpyBook/data\Streams.shp c:/ArcpyBook/ data\Streams_Buff.shp # FULL ROUND NONE #
Message 1 - Start Time: Tue Nov 13 22:23:04 2012
Message 2 - Failed to execute. Parameters are not valid.
Message 3 - ERROR 000735: Distance [value or field]: Value is required
Message 4 - Failed to execute (Buffer).
Message 5 - Failed at Tue Nov 13 22:23:04 2012 (Elapsed Time: 0.00
全部消息的数量为6,但是最后一条消息对应的索引数为5。这也就是为什么我们要在脚本代码中减去1的缘故。本案例中,由于脚本中发生错误,因此开始和结束时间相同。尽管如此,该案例仍然说明了如何来获取由工具生成的单个消息。

我要回帖

更多关于 网页脚本错误怎么解决 的文章

 

随机推荐