RunPython.cpp 15 KB

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