فهرست منبع

1、多次调用Py_Initialize会出错,因为Py_Finalize并不能完全释放所有python解析器产生的内存
这是Python的Bug,无解

scbc.sat2 5 سال پیش
والد
کامیت
7705c53f0a
3فایلهای تغییر یافته به همراه65 افزوده شده و 31 حذف شده
  1. 20 15
      RunPython/RunPython/RunPython.cpp
  2. 39 13
      RunPython/RunPython/ScriptExecutor.cpp
  3. 6 3
      RunPython/RunPython/ScriptExecutor.h

+ 20 - 15
RunPython/RunPython/RunPython.cpp

@@ -31,21 +31,26 @@ int _tmain(int argc, TCHAR* argv[], TCHAR* envp[])
 	}
 	else
 	{
-		// TODO: 在此处为应用程序的行为编写代码。
-		CScriptExecutor excutor;
-		excutor.InitScript(
-			//"E:\\bin\\ScbcCopyKey\\ScbcTest.py", 
-			"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",
-			"D:\\SAT\\log.txt", 
-			"",
-			EMBEDDED);
-		excutor.StartScript();
-
-		Sleep(500);
-		while( !excutor.IsScriptOver() )
-			Sleep(100);
-
-		Sleep(15000);
+		while(true)
+		{
+			// TODO: 在此处为应用程序的行为编写代码。
+			CScriptExecutor excutor;
+			excutor.InitScript(
+				//"E:\\bin\\ScbcCopyKey\\ScbcTest.py", 
+				"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",
+				"D:\\SAT\\log.txt", 
+				"",
+				SUBPROCESS);
+			excutor.StartScript();
+
+			Sleep(500);
+			while( !excutor.IsScriptOver() )
+				Sleep(100);
+
+			Sleep(2000);
+			OutputDebugString("--------------------------------------\n");
+		}
+
 	}
 
 	system("pause");

+ 39 - 13
RunPython/RunPython/ScriptExecutor.cpp

@@ -44,7 +44,7 @@ DWORD __stdcall CScriptExecutor::_WorkerThread(LPVOID lpParam)
 
 	if ( that->m_nRunType == EMBEDDED )
 	{
-		that->RedirectStdout();
+		that->RedirectProcessStdout();
 		ResumeThread(that->m_hLogThread);
 		that->RunEmbeddedScript();
 	}
@@ -109,12 +109,12 @@ DWORD __stdcall CScriptExecutor::_LogExportThread(LPVOID lpParam)
 	that->m_hLogThread = NULL;
 
 	// 结束重定向;
-	that->EndRedirectStdOut();
+	that->EndSubprocessStdOut();
 
 	return 0;
 }
 
-int CScriptExecutor::RedirectStdout(LPSTARTUPINFO si /*=NULL*/)
+int CScriptExecutor::RedirectSubprocessStdout(LPSTARTUPINFO si /*=NULL*/)
 {
 	if (m_nRunType == SUBPROCESS)
 	{
@@ -145,7 +145,16 @@ int CScriptExecutor::RedirectStdout(LPSTARTUPINFO si /*=NULL*/)
 
 		return 0;
 	}
-	else if (m_nRunType == EMBEDDED)
+
+	// 异常类型;
+	printf("Error:异常类型\n");
+
+	return -5;
+}
+
+int CScriptExecutor::RedirectProcessStdout()
+{
+	if (m_nRunType == EMBEDDED)
 	{
 		// 创建stdout的管道;
 		if (!CreatePipe(&m_hStdOutRead, &m_hStdOutWrite, NULL, 0))
@@ -287,7 +296,9 @@ int CScriptExecutor::RunEmbeddedScript()
 	}
 
 	// 初始化Python环境;
-	Py_Initialize();
+	if (!Py_IsInitialized())
+		Py_Initialize();
+
 	if (!Py_IsInitialized())
 	{
 		printf("Error:初始化Python环境失败\n");
@@ -380,7 +391,7 @@ int CScriptExecutor::RunScripProcess()
 		_stprintf_s(szCommandLine, _T("python -W ignore %s"), m_szScriptPath);
 
 	// 重定向输出;
-	RedirectStdout(&m_si);
+	RedirectSubprocessStdout(&m_si);
 	// 恢复日志线程;
 	ResumeThread(m_hLogThread);
 
@@ -529,9 +540,9 @@ BOOL CScriptExecutor::EndSubprocess()
 	return ret;
 }
 
-void CScriptExecutor::EndRedirectStdOut()
+void CScriptExecutor::EndProcessStdOut()
 {
-	OutputDebugString("Error:_dup2分配文件描述符失败\n");
+	OutputDebugString("--------------EndProcessStdOut----------------\n");
 #if 0 // 恢复失败,代码有问题
 	// 恢复标准输出(嵌入进程脚本);
 	if ( m_nRunType == EMBEDDED && m_hOldStdOutWrite)
@@ -554,7 +565,6 @@ void CScriptExecutor::EndRedirectStdOut()
 		}			
 	}
 #endif
-	printf("Error:_dup2分配文件描述符失败\n");
 
 	// 关闭重定向句柄;
 	if (m_hStdErrorWrite)
@@ -562,11 +572,27 @@ void CScriptExecutor::EndRedirectStdOut()
 	m_hStdErrorWrite = NULL;
 
 	// 只有子进程方式才关闭句柄;
-	if ( m_nRunType == SUBPROCESS && m_hStdOutWrite)
-	{
+	if ( m_hStdOutWrite)
 		CloseHandle(m_hStdOutWrite);
-		m_hStdOutWrite = NULL;
-	}
+	m_hStdOutWrite = NULL;
+
+	if (m_hStdOutRead)
+		CloseHandle(m_hStdOutRead);
+	m_hStdOutRead = NULL;	
+}
+
+void CScriptExecutor::EndSubprocessStdOut()
+{
+	OutputDebugString("--------------EndSubprocessStdOut----------------\n");
+	// 关闭重定向句柄;
+	if (m_hStdErrorWrite)
+		CloseHandle(m_hStdErrorWrite);
+	m_hStdErrorWrite = NULL;
+
+	// 只有子进程方式才关闭句柄;
+	if ( m_hStdOutWrite)
+		CloseHandle(m_hStdOutWrite);
+	m_hStdOutWrite = NULL;
 
 	if (m_hStdOutRead)
 		CloseHandle(m_hStdOutRead);

+ 6 - 3
RunPython/RunPython/ScriptExecutor.h

@@ -43,8 +43,10 @@ protected:
 	static DWORD WINAPI _WorkerThread(LPVOID lpParam);
 	// 日志导出线程;
 	static DWORD WINAPI _LogExportThread(LPVOID lpParam);
-	// 重定向标准输出;
-	int RedirectStdout(LPSTARTUPINFO si = NULL);
+	// 重定向本进程标准输出;
+	int RedirectProcessStdout();
+	// 重定子进程向标准输出;
+	int RedirectSubprocessStdout(LPSTARTUPINFO si = NULL);	
 	// 获取Python异常;
 	void CatchPythonException();
 	// 运行嵌入的脚本;
@@ -63,7 +65,8 @@ protected:
 	// 从管道读取日志;
 	void ReadFromPipe();
 	// 结束重定向句柄,恢复默认;
-	void EndRedirectStdOut();
+	void EndProcessStdOut();
+	void EndSubprocessStdOut();
 public:
 	// 初始脚本运行参数;
 	void InitScript(