From 73867d87d7e49113ab70c2cbceed301c80a2ae28 Mon Sep 17 00:00:00 2001 From: qianlifeng Date: Sat, 11 Jan 2014 15:02:17 +0800 Subject: [PATCH] research python plugin: seems ok in multiple thread now. --- .../WinAlfred.Plugin.DouBan/Images/movies.png | Bin 0 -> 2066 bytes Plugins/WinAlfred.Plugin.DouBan/main.py | 11 ++- WinAlfred/Commands/PluginCommand.cs | 79 ++++++++++++------ WinAlfred/MainWindow.xaml.cs | 2 +- WinAlfred/PluginLoader/BasePluginLoader.cs | 11 +++ WinAlfred/PluginLoader/PythonPluginLoader.cs | 6 +- WinAlfred/PluginLoader/PythonPluginWrapper.cs | 23 +++-- 7 files changed, 85 insertions(+), 47 deletions(-) create mode 100644 Plugins/WinAlfred.Plugin.DouBan/Images/movies.png diff --git a/Plugins/WinAlfred.Plugin.DouBan/Images/movies.png b/Plugins/WinAlfred.Plugin.DouBan/Images/movies.png new file mode 100644 index 0000000000000000000000000000000000000000..a8ec632c4fd468f983d716ba542bbe189f3f3ba8 GIT binary patch literal 2066 zcmV+t2<`WYP)|0l|va_!L z|Mz|W?>pXBx88D>e)Ga!J^72LHEULn7A#t!i@WBiR%_Lvj}JKzVcPwbI$|n?w&1RYvJvQ zRtDbu^I!h19Xr0St+(B+Z-3{9x^&?RZM^bYEnc!l?H!#ueE6^?x0hbpqv>rOT6g(o zUA5_Y^~_nQ*>f(@(9nrVyMi8iaHm>Yrt6x`H|oyqI|RI0U`~Xf&DhG|4L4k0cHZN? z=xFc2Whw8x_dYXbv@?A241e&WM@|t%F_}xL)oN_NcL(K4E8aQUTFUI-_bTta`!3cPY!uUqvcJF?kPmUa+TB=fSjstW8C(ef8Vn84Kg`>kI8L#VU9s^h)$0vqUh+X|HXB;BXsJr2s#dOCr=?3*sakE-vc8p{ zPoQVc9QF1t)vC*`)SC4h)!n^N%a*Rtso~)XNjc}VZQFL$YOUI^;To-3yGiXGvvku< zH>=rfPVB4K>+0)Ur&_g58?M-*wd*#iwY5XLc0H-*o_lVBz?4*2xoQLRdKWUit&LJt zp{uKtz58CpWf`9wIl|D;aUOf@N9^CfkE=IdN4ZiX2-dA#$1~47&G5(w{huCXaA1J1 z-@J|f{sFGO_Bu-C3ZtWSzIEH}?A-YvpB?>l0@F@Bc`7m(YX}a&lbDDz&S3-+popQ-B^x_T6epM%Ol)y+gkmr@A}(35P_j96ki~~QWIpp`PRIw8iVy-O z4VVBvb0lsqu^dw{Cl7pZ*kFiEgozV^wZyT7NZ8n7OA&Dl7>leh7-D&1W3d53ImTrM z=RH{@nyI51JW3(;qA?~CzJNfGkb#&81rZEb6EGIMu|$!GZA3LOB(WtyIK?zFF_MYl zx@Wi^7#|C`Mn*Os@J)x(fSMUZfevdfOn{IVDKAe52AhCULZxJ>mJK#CWC4zk2hL=k zA!j(91)LK~L;eHnReS*xK^zK^Scna7?28CQ2JfL1S(0*0DKU6pU?gxl^E4zH7Gw>S zip!G-5}+i=1WgYRmgn*nbvDn(F>AhA#~1!#aM z1_F2sE`S0=`4pzGJTU3~1I|pTeNzcop#Nis9~pyk392!aEtCr@qud}Q2sR%BgpeP$ zh3f;8-dYxn%jY7n3Y?F5&I5qYfJ#(Y3V4%S<~bKjLyq7>z8*}mZqGfmg3WKV#n}QX zlP>H5`NB#U$fYl^g{Weai`0i4uvGZh7Qo7j4MF*O$Z}9+U<)G*SWOk-R1chWp-c`g zfpdkjU4C&^SkUnKe6tWJsnoUU4yw_7` zG-1p^!{uvP3XKLdQb-%n%bD>#6Vq@y7hpNcE}*#eZG3(b_up%)oD_D_cE?oYs@z)_%a zmVgCXfjPikz>UCSpoRZUI}LmUyaqfEd= 2 else "Null" + res["SubTitle"] = "Year: " + year + " Score: " + score + " Alias: " + alias res["ActionName"] = "openUrl" + res["IcoPath"] = "Images\\movies.png" res["ActionPara"] = i.select("a[href]")[0]["href"] results.append(res) return json.dumps(results) def openUrl(url): - pass + webbrowser.open(url) if __name__ == "__main__": print query("movie geo") diff --git a/WinAlfred/Commands/PluginCommand.cs b/WinAlfred/Commands/PluginCommand.cs index f30b667ac3..81f5e739d1 100644 --- a/WinAlfred/Commands/PluginCommand.cs +++ b/WinAlfred/Commands/PluginCommand.cs @@ -1,6 +1,8 @@ using System; using System.Collections.Generic; +using System.Linq; using System.Threading; +using Python.Runtime; using WinAlfred.Helper; using WinAlfred.Plugin; using WinAlfred.PluginLoader; @@ -9,6 +11,9 @@ namespace WinAlfred.Commands { public class PluginCommand : BaseCommand { + private string currentPythonModulePath = string.Empty; + private IntPtr GIL; + public PluginCommand(MainWindow mainWindow) : base(mainWindow) { @@ -17,36 +22,56 @@ namespace WinAlfred.Commands public override void Dispatch(Query q) { - - foreach (PluginPair pair in Plugins.AllPlugins) + PluginPair thirdPlugin = Plugins.AllPlugins.FirstOrDefault(o => o.Metadata.ActionKeyword == q.ActionName); + if (thirdPlugin != null && !string.IsNullOrEmpty(thirdPlugin.Metadata.ActionKeyword)) { - if (pair.Metadata.ActionKeyword == q.ActionName) + if (thirdPlugin.Metadata.Language == AllowedLanguage.Python) { - PluginPair pair1 = pair; - ThreadPool.QueueUserWorkItem(state => - { - try - { - List r = pair1.Plugin.Query(q); - r.ForEach(o => - { - o.PluginDirectory = pair1.Metadata.PluginDirecotry; - o.OriginQuery = q; - }); - UpdateResultView(r); - } - catch (Exception queryException) - { - Log.Error(string.Format("Plugin {0} query failed: {1}", pair1.Metadata.Name, - queryException.Message)); -#if (DEBUG) - { - throw; - } -#endif - } - }); + SwitchPythonEnv(thirdPlugin); } + ThreadPool.QueueUserWorkItem(t => + { + try + { + List r = thirdPlugin.Plugin.Query(q); + r.ForEach(o => + { + o.PluginDirectory = thirdPlugin.Metadata.PluginDirecotry; + o.OriginQuery = q; + }); + UpdateResultView(r); + } + catch (Exception queryException) + { + Log.Error(string.Format("Plugin {0} query failed: {1}", thirdPlugin.Metadata.Name, + queryException.Message)); +#if (DEBUG) + { + throw; + } +#endif + } + }); + } + } + + private void SwitchPythonEnv(PluginPair thirdPlugin) + { + if (currentPythonModulePath != thirdPlugin.Metadata.PluginDirecotry) + { + //this must initial in main thread + currentPythonModulePath = thirdPlugin.Metadata.PluginDirecotry; + + if (GIL != IntPtr.Zero) + { + Runtime.PyEval_RestoreThread(GIL); + PythonEngine.Shutdown(); + } + PythonEngine.Initialize(); + IntPtr pyStrPtr = Runtime.PyString_FromString(thirdPlugin.Metadata.PluginDirecotry); + IntPtr SysDotPath = Runtime.PySys_GetObject("path"); + Runtime.PyList_Append(SysDotPath, pyStrPtr); + GIL = PythonEngine.BeginAllowThreads(); } } } diff --git a/WinAlfred/MainWindow.xaml.cs b/WinAlfred/MainWindow.xaml.cs index 12af291774..acef9d0906 100644 --- a/WinAlfred/MainWindow.xaml.cs +++ b/WinAlfred/MainWindow.xaml.cs @@ -45,7 +45,7 @@ namespace WinAlfred void MainWindow_Closed(object sender, EventArgs e) { - PythonEngine.Shutdown(); + //PythonEngine.Shutdown(); } private void InitProgressbarAnimation() diff --git a/WinAlfred/PluginLoader/BasePluginLoader.cs b/WinAlfred/PluginLoader/BasePluginLoader.cs index 6a48e7aa0e..3acf56d129 100644 --- a/WinAlfred/PluginLoader/BasePluginLoader.cs +++ b/WinAlfred/PluginLoader/BasePluginLoader.cs @@ -117,5 +117,16 @@ namespace WinAlfred.PluginLoader return null; } } + + ///// + ///// Change python execute file name to unique file name using GUID + ///// this is because if two pythong plugin use the same + ///// + ///// + ///// + //private static PluginMetadata filterPythonMetadata(PluginMetadata metadata) + //{ + + //} } } diff --git a/WinAlfred/PluginLoader/PythonPluginLoader.cs b/WinAlfred/PluginLoader/PythonPluginLoader.cs index 52509f8aaa..a31fea21fd 100644 --- a/WinAlfred/PluginLoader/PythonPluginLoader.cs +++ b/WinAlfred/PluginLoader/PythonPluginLoader.cs @@ -1,4 +1,5 @@ -using System.Collections.Generic; +using System; +using System.Collections.Generic; using System.Linq; using System.Threading; using Python.Runtime; @@ -11,8 +12,7 @@ namespace WinAlfred.PluginLoader static PythonPluginLoader() { - PythonEngine.Initialize(); - PythonEngine.BeginAllowThreads(); + } public override List LoadPlugin() diff --git a/WinAlfred/PluginLoader/PythonPluginWrapper.cs b/WinAlfred/PluginLoader/PythonPluginWrapper.cs index 4288b4eddd..1ecba68c8c 100644 --- a/WinAlfred/PluginLoader/PythonPluginWrapper.cs +++ b/WinAlfred/PluginLoader/PythonPluginWrapper.cs @@ -10,6 +10,7 @@ namespace WinAlfred.PluginLoader { public class PythonPluginWrapper : IPlugin { + private PluginMetadata metadata; public PythonPluginWrapper(PluginMetadata metadata) @@ -21,13 +22,13 @@ namespace WinAlfred.PluginLoader { try { - string s = InvokeFunc(metadata.PluginDirecotry, metadata.ExecuteFileName.Replace(".py", ""),"query",query.RawQuery); - if (string.IsNullOrEmpty(s)) + string jsonResult = InvokeFunc(metadata.PluginDirecotry, metadata.ExecuteFileName.Replace(".py", ""), "query", query.RawQuery); + if (string.IsNullOrEmpty(jsonResult)) { return new List(); } - List o = JsonConvert.DeserializeObject>(s); + List o = JsonConvert.DeserializeObject>(jsonResult); List r = new List(); foreach (PythonResult pythonResult in o) { @@ -42,22 +43,20 @@ namespace WinAlfred.PluginLoader } catch (Exception) { - - throw; +#if (DEBUG) + { + throw; + } +#endif } } - private string InvokeFunc(string path, string moduleName,string func, string para) + private string InvokeFunc(string path, string moduleName, string func, string para) { IntPtr gs = PythonEngine.AcquireLock(); - IntPtr pyStrPtr = Runtime.PyString_FromString(path); - IntPtr SysDotPath = Runtime.PySys_GetObject("path"); - Runtime.PyList_Append(SysDotPath, pyStrPtr); - PyObject module = PythonEngine.ImportModule(moduleName); - module = PythonEngine.ReloadModule(module); PyObject res = module.InvokeMethod(func, new PyString(para)); string json = Runtime.GetManagedString(res.Handle); @@ -68,7 +67,7 @@ namespace WinAlfred.PluginLoader public void Init(PluginInitContext context) { - + } } }