RunPython.cpp 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573
  1. // RunPython.cpp : 定义 DLL 应用程序的导出函数。
  2. //
  3. #include "stdafx.h"
  4. #include "RunPython.h"
  5. #include "ScriptExecutor.h"
  6. #ifdef _DEBUG
  7. #define new DEBUG_NEW
  8. #endif
  9. // 唯一的应用程序对象
  10. CWinApp theApp;
  11. using namespace std;
  12. BOOL Python27Dir(LPTSTR lpPython27Dir, int nBufferLen);
  13. int _tmain(int argc, TCHAR* argv[], TCHAR* envp[])
  14. {
  15. int nRetCode = 0;
  16. // 初始化 MFC 并在失败时显示错误
  17. if (!AfxWinInit(::GetModuleHandle(NULL), NULL, ::GetCommandLine(), 0))
  18. {
  19. // TODO: 更改错误代码以符合您的需要
  20. _tprintf(_T("错误: MFC 初始化失败\n"));
  21. nRetCode = 1;
  22. }
  23. else
  24. {
  25. // TODO: 在此处为应用程序的行为编写代码。
  26. CScriptExecutor excutor;
  27. excutor.InitScript("E:\\bin\\ScbcCopyKey\\ScbcTest.py",
  28. "D:\\SAT\\log.txt",
  29. "",
  30. EMBEDDED);
  31. excutor.StartScript();
  32. Sleep(500);
  33. while( !excutor.IsScriptOver() )
  34. Sleep(100);
  35. }
  36. system("pause");
  37. return nRetCode;
  38. }
  39. void CatchPythonException()
  40. {
  41. if ( !Py_IsInitialized() )
  42. {
  43. printf("未初始化Python环境\n");
  44. return;
  45. }
  46. if ( !PyErr_Occurred() )
  47. {
  48. printf("没有异常产生\n");
  49. return;
  50. }
  51. // 捕获异常;
  52. const char *pszErrMsg = NULL;
  53. TCHAR *pszTraceback = NULL;
  54. PyObject *pPyType = NULL;
  55. PyObject *pPyValue = NULL;
  56. PyObject *pPyTraceback = NULL;
  57. // 非控制台,使用PyErr_Fetch捕获异常;
  58. PyErr_Fetch(&pPyType, &pPyValue, &pPyTraceback);
  59. PyErr_NormalizeException(&pPyType, &pPyValue, &pPyTraceback); // 可有可无,不影响获取异常;
  60. if ( pPyValue )
  61. {
  62. PyObject *pPyStr = PyObject_Str(pPyValue);
  63. if ( PyString_Check(pPyStr) )
  64. {
  65. pszErrMsg = PyString_AsString(pPyStr);
  66. if ( pszErrMsg )
  67. printf("Error Info=>%s\n",pszErrMsg);
  68. if ( pPyTraceback )
  69. {
  70. PyObject *pPyTraceModule = PyImport_ImportModule("traceback");
  71. if ( !pPyTraceModule )
  72. {
  73. printf("导入traceback模块失败\n");
  74. return;
  75. }
  76. #if 1
  77. PyObject *pPyModuleDict = PyModule_GetDict(pPyTraceModule);
  78. if ( pPyModuleDict )
  79. {
  80. PyObject *pPyFunc = PyDict_GetItemString(pPyModuleDict, "format_exception");
  81. if ( !pPyFunc || !PyCallable_Check(pPyFunc) )
  82. {
  83. printf("加载format_exception失败\n");
  84. return;
  85. }
  86. PyObject *pErroList = PyObject_CallFunctionObjArgs(pPyFunc, pPyType, pPyValue, pPyTraceback, NULL);
  87. if ( pErroList )
  88. {
  89. int nSize = PyList_Size(pErroList);
  90. for ( int i = 0; i < nSize; i++ )
  91. {
  92. pszErrMsg = PyString_AsString(PyList_GetItem(pErroList, i));
  93. printf("%s", pszErrMsg);
  94. }
  95. }
  96. }
  97. Py_XDECREF(pPyTraceModule);
  98. #else // 不细分Item;
  99. PyObject *pPyFunc = PyObject_GetAttrString(pPyTraceModule, "format_exception");
  100. if ( !pPyFunc || !PyCallable_Check(pPyFunc) )
  101. {
  102. printf("加载format_exception失败\n");
  103. return;
  104. }
  105. PyObject *pPyResult = PyObject_CallFunctionObjArgs(pPyFunc, pPyType, pPyValue, pPyTraceback, NULL);
  106. pPyStr = PyObject_Str(pPyResult);
  107. pszErrMsg = PyString_AsString(pPyStr);
  108. if ( pszErrMsg )
  109. printf("%s\n",pszErrMsg);
  110. Py_DECREF(pPyResult);
  111. Py_XDECREF(pPyTraceModule);
  112. #endif
  113. }
  114. }
  115. }
  116. }
  117. // 从注册表获取 Python27路径;
  118. BOOL Python27Dir(LPTSTR lpPython27Dir, int nBufferLen)
  119. {
  120. HKEY hKey;
  121. int ret = RegOpenKeyEx(HKEY_LOCAL_MACHINE, _T("SOFTWARE\\WOW6432Node\\Python\\PythonCore\\2.7\\InstallPath"), 0, KEY_QUERY_VALUE, &hKey);
  122. if (ret != ERROR_SUCCESS)
  123. return FALSE;
  124. //读取KEY
  125. DWORD dwType = REG_SZ; //数据类型
  126. DWORD cbData = nBufferLen;
  127. ret = RegQueryValueEx(hKey, _T(""), NULL, &dwType, (LPBYTE)lpPython27Dir, &cbData);
  128. if (ret != ERROR_SUCCESS)
  129. {
  130. RegCloseKey(hKey);
  131. return FALSE;
  132. }
  133. RegCloseKey(hKey);
  134. return TRUE;
  135. }
  136. // 运行Python脚本;
  137. RUNPYTHON_API int RunPython(LPCTSTR lpScriptFile, LPCTSTR lpExtraSentence)
  138. {
  139. // 参数有效性判断;
  140. if ( !lpScriptFile || !PathFileExists(lpScriptFile) )
  141. return -1;
  142. // 初始化Python环境;
  143. Py_Initialize();
  144. if ( !Py_IsInitialized() )
  145. return -2;
  146. // 解析脚本路径和脚本名称;
  147. std::string scriptdir;
  148. TCHAR szDrive[_MAX_DRIVE] = { 0 };
  149. TCHAR szDir[_MAX_DIR] = { 0 };
  150. TCHAR szExt[_MAX_EXT] = { 0 };
  151. TCHAR szFilename[_MAX_FNAME] = { 0 };
  152. TCHAR szScriptDir[MAX_PATH] = { 0 };
  153. _tsplitpath_s(lpScriptFile, szDrive, szDir, szFilename, szExt);
  154. _stprintf_s(szScriptDir, _T("%s%s"), szDrive, szDir);
  155. // 缓存一份路径;
  156. scriptdir = szScriptDir;
  157. // 将'\'转换成'/', Python才设置运行目录成功;
  158. int len = _tcslen(szScriptDir);
  159. for ( int i = 0; i < len; i++ )
  160. {
  161. if ( szScriptDir[i] == '\\' )
  162. szScriptDir[i] = '/';
  163. }
  164. //szScriptDir[len-1] = '\0';
  165. TCHAR szExecuteDir[MAX_PATH] = { 0 };
  166. _stprintf_s(szExecuteDir, _T("sys.path.append(\"%s\")"), szScriptDir);
  167. // 添加系统模块,并指定当前脚本路径为运行路径;
  168. PyRun_SimpleString("import sys");
  169. PyRun_SimpleString(szExecuteDir);
  170. // 运行额外的语句,一般用于传递命令行参数;
  171. if ( lpExtraSentence )
  172. PyRun_SimpleString(lpExtraSentence);
  173. // 注意:脚本名称尽量不要与系统目录其他py文件相同;
  174. // 导入脚本,以脚本名称为模块名加载;
  175. PyObject *pModuleObj = PyImport_ImportModule(szFilename);
  176. if ( !pModuleObj )
  177. {
  178. printf("=>加载模块失败\n");
  179. Py_Finalize();
  180. return -3;
  181. }
  182. // 获取脚本的主函数名称(规定所有脚本的主函数名为main)
  183. // 加载函数:注意,如果目录下有同名的脚本文件,可能会加载失败;
  184. PyObject *pFunction = PyObject_GetAttrString(pModuleObj, "main");
  185. if ( !pFunction || !PyCallable_Check(pFunction) )
  186. {
  187. printf("=>加载函数失败\n");
  188. Py_Finalize();
  189. return -4;
  190. }
  191. // 执行main函数;
  192. PyObject *pResult = PyObject_CallObject(pFunction, NULL);
  193. if ( !pResult )
  194. {
  195. printf("=>运行函数失败\n");
  196. Py_Finalize();
  197. return -5;
  198. }
  199. Py_Finalize();
  200. return 0;
  201. }
  202. RUNPYTHON_API int RunPythonEx(LPCTSTR lpScriptFile, LPCTSTR lpExtraSentence)
  203. {
  204. // 参数有效性判断;
  205. if ( !lpScriptFile || !PathFileExists(lpScriptFile) )
  206. return -1;
  207. // 初始化Python环境;
  208. Py_Initialize();
  209. if ( !Py_IsInitialized() )
  210. return -2;
  211. // 解析脚本路径和脚本名称;
  212. std::string scriptdir;
  213. TCHAR szDrive[_MAX_DRIVE] = { 0 };
  214. TCHAR szDir[_MAX_DIR] = { 0 };
  215. TCHAR szExt[_MAX_EXT] = { 0 };
  216. TCHAR szFilename[_MAX_FNAME] = { 0 };
  217. TCHAR szScriptDir[MAX_PATH] = { 0 };
  218. _tsplitpath_s(lpScriptFile, szDrive, szDir, szFilename, szExt);
  219. _stprintf_s(szScriptDir, _T("%s%s"), szDrive, szDir);
  220. // 缓存一份路径;
  221. scriptdir = szScriptDir;
  222. // 将'\'转换成'/', Python才设置运行目录成功;
  223. int len = _tcslen(szScriptDir);
  224. for ( int i = 0; i < len; i++ )
  225. {
  226. if ( szScriptDir[i] == '\\' )
  227. szScriptDir[i] = '/';
  228. }
  229. //szScriptDir[len-1] = '\0';
  230. //////////////////////////////////////////////////////////////////////////
  231. TCHAR szExecuteDir[MAX_PATH] = { 0 };
  232. _stprintf_s(szExecuteDir, _T("sys.path.append(\"%s\")"), szScriptDir);
  233. // 添加系统模块,并指定当前脚本路径为运行路径;
  234. PyRun_SimpleString("import sys");
  235. PyRun_SimpleString(szExecuteDir);
  236. // 运行额外的语句,一般用于传递命令行参数;
  237. if ( lpExtraSentence )
  238. PyRun_SimpleString(lpExtraSentence);
  239. /*
  240. PyObject* main = PyModule_GetDict(PyImport_AddModule("__main__"));
  241. PyObject *res = PyRun_String(由文件内容, Py_file_input, main, main);
  242. */
  243. // 注意:脚本名称尽量不要与系统目录其他py文件相同;
  244. // 导入脚本,以脚本名称为模块名加载;
  245. PyObject *pModuleObj = PyImport_ImportModule(szFilename);
  246. if ( !pModuleObj )
  247. {
  248. printf("=>加载模块失败\n");
  249. Py_Finalize();
  250. return -3;
  251. }
  252. // 获取脚本的主函数名称(规定所有脚本的主函数名为main)
  253. // 加载函数:注意,如果目录下有同名的脚本文件,可能会加载失败;
  254. PyObject *pFunction = PyObject_GetAttrString(pModuleObj, "main");
  255. if ( !pFunction || !PyCallable_Check(pFunction) )
  256. {
  257. printf("=>加载函数失败\n");
  258. Py_Finalize();
  259. return -4;
  260. }
  261. // 执行main函数;
  262. //PyObject *pResult = PyObject_CallFunctionObjArgs(pFunction, pType, pValue, pTraceback, NULL);
  263. PyObject *pResult = PyObject_CallObject(pFunction, NULL);
  264. if ( !pResult )
  265. {
  266. printf("=>运行函数失败\n");
  267. #if 0
  268. // 捕获异常;
  269. const char *pszErrMsg = NULL;
  270. TCHAR *pszTraceback = NULL;
  271. PyObject *pType = NULL;
  272. PyObject *pValue = NULL;
  273. PyObject *pTraceback = NULL;
  274. // 非控制台,使用PyErr_Fetch捕获异常;
  275. PyErr_Fetch(&pType, &pValue, &pTraceback);
  276. PyErr_NormalizeException(&pType,&pValue,&pTraceback);
  277. if ( pValue )
  278. {
  279. PyObject *pStr = PyObject_Str(pValue);
  280. if ( pStr )
  281. {
  282. //pszErrMsg = PyUnicode_AsUTF8String(pStr);
  283. int line, offset;
  284. TCHAR *pszMsg, *pszFile, *pszText;
  285. int res = PyArg_ParseTuple(pValue, "s(siis)", &pszMsg, &pszFile, &line, &offset, &pszText);
  286. //Q_UNUSED();
  287. PyObject *line_no = PyObject_GetAttrString(pValue, "lineno");
  288. PyObject *line_no_str = PyObject_Str(line_no);
  289. PyObject *line_no_unicode = PyUnicode_AsEncodedString(line_no_str, "utf-8", "Error");
  290. char *actual_line_no = PyBytes_AsString(line_no_unicode);
  291. printf("actual_line_no --%s\n", actual_line_no);
  292. }
  293. }
  294. #else
  295. CatchPythonException();
  296. #endif
  297. PyErr_Print();
  298. Py_Finalize();
  299. return -5;
  300. }
  301. Py_DECREF(pResult);
  302. Py_Finalize();
  303. return 0;
  304. }
  305. // lpScriptFile:脚本文件;
  306. // lpCommand:命令行参数;
  307. RUNPYTHON_API int CallPython(LPCTSTR lpScriptFile, LPCTSTR lpCommand)
  308. {
  309. if ( !lpScriptFile || !PathFileExists(lpScriptFile) )
  310. {
  311. printf("参数无效\n");
  312. return -1;
  313. }
  314. // 获取Python27进程目录;
  315. TCHAR szPython27Dir[MAX_PATH] = {0};
  316. TCHAR szPython27Exe[MAX_PATH] = {0};
  317. if ( !Python27Dir(szPython27Dir, MAX_PATH) )
  318. {
  319. printf("获取Python27目录失败\n");
  320. return -2;
  321. }
  322. _stprintf_s(szPython27Exe, _T("%spython.exe"), szPython27Dir);
  323. STARTUPINFO si;
  324. ::memset(&si, 0 ,sizeof(si));
  325. si.cb = sizeof(si);
  326. PROCESS_INFORMATION pi;
  327. ::memset(&pi, 0 ,sizeof(pi));
  328. TCHAR szCommandLine[MAX_PATH] = {0};
  329. if ( lpCommand )
  330. _stprintf_s(szCommandLine, _T("python -W ignore %s %s"), lpScriptFile, lpCommand);
  331. else
  332. _stprintf_s(szCommandLine, _T("python -W ignore %s"), lpScriptFile);
  333. // 启动子进程;
  334. if( !CreateProcess(
  335. NULL, // No module name (use command line)
  336. szCommandLine, // Command line
  337. NULL, // Process handle not inheritable
  338. NULL, // Thread handle not inheritable
  339. FALSE, // Set handle inheritance to TRUE
  340. 0, // No creation flags
  341. NULL, // Use parent's environment block
  342. NULL, // Use parent's starting directory
  343. &si, // Pointer to STARTUPINFO structure
  344. &pi ) // Pointer to PROCESS_INFORMATION structure
  345. )
  346. {
  347. printf( "CreateProcess failed (%d).\n", GetLastError() );
  348. return -3;
  349. }
  350. // Wait until child process exits.
  351. WaitForSingleObject( pi.hProcess, INFINITE );
  352. // Close process and thread handles.
  353. CloseHandle( pi.hProcess );
  354. CloseHandle( pi.hThread );
  355. return 0;
  356. }
  357. // 读出stdout
  358. BOOL ReadFromPipe(HANDLE hStdOutRead)
  359. {
  360. char out_buffer[BUFSIZE] = {0};
  361. DWORD dwRead;
  362. BOOL bSuccess = FALSE;
  363. //用WriteFile,从hStdOutRead读出子进程stdout输出的数据,数据结果在out_buffer中,长度为dwRead
  364. bSuccess = ReadFile( hStdOutRead, out_buffer, BUFSIZE, &dwRead, NULL);
  365. if ((bSuccess) && (dwRead!=0)) //如果成功了,且长度>0
  366. {
  367. // 此处加入你自己的代码
  368. // 比如:将数据写入文件或显示到窗口中
  369. OutputDebugString(out_buffer);
  370. }
  371. return bSuccess;
  372. }
  373. bool GetOutput( HANDLE hStdOutRead, int timeout )
  374. {
  375. if( NULL == hStdOutRead )
  376. {
  377. return false;
  378. }
  379. char buffer[4096] = {0};
  380. DWORD readBytes = 0;
  381. while( timeout > 0 )
  382. {
  383. //对管道数据进行读,但不会删除管道里的数据,如果没有数据,就立即返回
  384. if( FALSE == PeekNamedPipe( hStdOutRead, buffer, sizeof(buffer) - 1, &readBytes, 0, NULL ) )
  385. {
  386. return false;
  387. }
  388. //检测是否读到数据,如果没有数据,继续等待
  389. if( 0 == readBytes )
  390. {
  391. ::Sleep(200);
  392. timeout -= 200;
  393. continue;
  394. }
  395. readBytes = 0;
  396. if( ::ReadFile( hStdOutRead, buffer, sizeof(buffer) - 1, &readBytes, NULL) )
  397. {
  398. OutputDebugString(buffer);
  399. return true;
  400. }
  401. else
  402. {
  403. return false;
  404. }
  405. }
  406. return false;
  407. }
  408. // lpScriptFile:脚本文件;
  409. // lpCommand:命令行参数;
  410. RUNPYTHON_API int CallPythonEx(LPCTSTR lpScriptFile, LPCTSTR lpCommand)
  411. {
  412. if ( !lpScriptFile || !PathFileExists(lpScriptFile) )
  413. {
  414. printf("参数无效\n");
  415. return -1;
  416. }
  417. // 获取Python27进程目录;
  418. TCHAR szPython27Dir[MAX_PATH] = {0};
  419. TCHAR szPython27Exe[MAX_PATH] = {0};
  420. if ( !Python27Dir(szPython27Dir, MAX_PATH) )
  421. {
  422. printf("获取Python27目录失败\n");
  423. return -2;
  424. }
  425. _stprintf_s(szPython27Exe, _T("%spython.exe"), szPython27Dir);
  426. STARTUPINFO si;
  427. ::memset(&si, 0 ,sizeof(si));
  428. si.cb = sizeof(si);
  429. GetStartupInfo(&si);
  430. PROCESS_INFORMATION pi;
  431. ::memset(&pi, 0 ,sizeof(pi));
  432. TCHAR szCommandLine[MAX_PATH] = {0};
  433. if ( lpCommand )
  434. _stprintf_s(szCommandLine, _T("python -W ignore %s %s"), lpScriptFile, lpCommand);
  435. else
  436. _stprintf_s(szCommandLine, _T("python -W ignore %s"), lpScriptFile);
  437. SECURITY_ATTRIBUTES sa;
  438. sa.bInheritHandle = TRUE;
  439. sa.lpSecurityDescriptor = NULL;
  440. sa.nLength = sizeof(sa);
  441. // 创建stdout的管道;
  442. HANDLE hStdOutRead, hStdOutWrite;
  443. if ( !CreatePipe(&hStdOutRead, &hStdOutWrite, &sa, 0) )
  444. {
  445. printf("创建stdout管道失败\n");
  446. return -3;
  447. }
  448. // 创建stderr的管道,由于stderr一般就是stdout,直接复制句柄;
  449. HANDLE hStdErrWrite;
  450. if ( !DuplicateHandle(GetCurrentProcess(), hStdOutWrite, GetCurrentProcess(), &hStdErrWrite, 0, TRUE, DUPLICATE_SAME_ACCESS) )
  451. {
  452. printf("创建stderr管道失败\n");
  453. return -3;
  454. }
  455. si.dwFlags |= STARTF_USESTDHANDLES;
  456. // 将子进程的stdout输出到句柄hStdOutWrite;
  457. si.hStdOutput = hStdOutWrite;
  458. // 将子进程的stderr输出到句柄hStdErrWrite;
  459. si.hStdError = hStdErrWrite;
  460. // 启动子进程;
  461. if( !CreateProcess(
  462. NULL, // No module name (use command line)
  463. szCommandLine, // Command line
  464. NULL, // Process handle not inheritable
  465. NULL, // Thread handle not inheritable
  466. TRUE, // 如果不设置为TRUE,重定向无效;
  467. 0, // No creation flags
  468. NULL, // Use parent's environment block
  469. NULL, // Use parent's starting directory
  470. &si, // Pointer to STARTUPINFO structure
  471. &pi ) // Pointer to PROCESS_INFORMATION structure
  472. )
  473. {
  474. printf( "CreateProcess failed (%d).\n", GetLastError() );
  475. return -3;
  476. }
  477. #ifdef _DEBUG
  478. DWORD process_exit_code = 0;
  479. while (GetExitCodeProcess(pi.hProcess, &process_exit_code))
  480. {
  481. // 读取stdout、stderr;
  482. //GetOutput(hStdOutRead, 3000);
  483. ReadFromPipe(hStdOutRead);
  484. if ( process_exit_code != STILL_ACTIVE )
  485. break;
  486. }
  487. #endif
  488. // Wait until child process exits.
  489. WaitForSingleObject( pi.hProcess, INFINITE );
  490. // Close process and thread handles.
  491. CloseHandle( pi.hProcess );
  492. CloseHandle( pi.hThread );
  493. return 0;
  494. }