X Tutup
using System; using NUnit.Framework; using Python.Runtime; namespace Python.EmbeddingTest { public class PyScopeTest { private PyScope ps; [SetUp] public void SetUp() { using (Py.GIL()) { ps = Py.CreateScope("test"); } } [TearDown] public void Dispose() { using (Py.GIL()) { ps.Dispose(); ps = null; } } /// /// Eval a Python expression and obtain its return value. /// [Test] public void TestEval() { using (Py.GIL()) { ps.Set("a", 1); var result = ps.Eval("a + 2"); Assert.AreEqual(3, result); } } /// /// Exec Python statements and obtain the variables created. /// [Test] public void TestExec() { using (Py.GIL()) { ps.Set("bb", 100); //declare a global variable ps.Set("cc", 10); //declare a local variable ps.Exec("aa = bb + cc + 3"); var result = ps.Get("aa"); Assert.AreEqual(113, result); } } /// /// Compile an expression into an ast object; /// Execute the ast and obtain its return value. /// [Test] public void TestCompileExpression() { using (Py.GIL()) { ps.Set("bb", 100); //declare a global variable ps.Set("cc", 10); //declare a local variable PyObject script = PythonEngine.Compile("bb + cc + 3", "", RunFlagType.Eval); var result = ps.Execute(script); Assert.AreEqual(113, result); } } /// /// Compile Python statements into an ast object; /// Execute the ast; /// Obtain the local variables created. /// [Test] public void TestCompileStatements() { using (Py.GIL()) { ps.Set("bb", 100); //declare a global variable ps.Set("cc", 10); //declare a local variable PyObject script = PythonEngine.Compile("aa = bb + cc + 3", "", RunFlagType.File); ps.Execute(script); var result = ps.Get("aa"); Assert.AreEqual(113, result); } } /// /// Create a function in the scope, then the function can read variables in the scope. /// It cannot write the variables unless it uses the 'global' keyword. /// [Test] public void TestScopeFunction() { using (Py.GIL()) { ps.Set("bb", 100); ps.Set("cc", 10); ps.Exec( "def func1():\n" + " bb = cc + 10\n"); dynamic func1 = ps.Get("func1"); func1(); //call the function, it can be called any times var result = ps.Get("bb"); Assert.AreEqual(100, result); ps.Set("bb", 100); ps.Set("cc", 10); ps.Exec( "def func2():\n" + " global bb\n" + " bb = cc + 10\n"); dynamic func2 = ps.Get("func2"); func2(); result = ps.Get("bb"); Assert.AreEqual(20, result); } } /// /// Create a class in the scope, the class can read variables in the scope. /// Its methods can write the variables with the help of 'global' keyword. /// [Test] public void TestScopeClass() { using (Py.GIL()) { dynamic _ps = ps; _ps.bb = 100; ps.Exec( "class Class1():\n" + " def __init__(self, value):\n" + " self.value = value\n" + " def call(self, arg):\n" + " return self.value + bb + arg\n" + //use scope variables " def update(self, arg):\n" + " global bb\n" + " bb = self.value + arg\n" //update scope variable ); dynamic obj1 = _ps.Class1(20); var result = obj1.call(10).As(); Assert.AreEqual(130, result); obj1.update(10); result = ps.Get("bb"); Assert.AreEqual(30, result); } } /// /// Import a python module into the session. /// Equivalent to the Python "import" statement. /// [Test] public void TestImportModule() { using (Py.GIL()) { dynamic sys = ps.Import("sys"); Assert.IsTrue(ps.Contains("sys")); ps.Exec("sys.attr1 = 2"); var value1 = ps.Eval("sys.attr1"); var value2 = sys.attr1.As(); Assert.AreEqual(2, value1); Assert.AreEqual(2, value2); //import as ps.Import("sys", "sys1"); Assert.IsTrue(ps.Contains("sys1")); } } /// /// Create a scope and import variables from a scope, /// exec Python statements in the scope then discard it. /// [Test] public void TestImportScope() { using (Py.GIL()) { ps.Set("bb", 100); ps.Set("cc", 10); using (var scope = Py.CreateScope()) { scope.Import(ps, "ps"); scope.Exec("aa = ps.bb + ps.cc + 3"); var result = scope.Get("aa"); Assert.AreEqual(113, result); } Assert.IsFalse(ps.Contains("aa")); } } /// /// Create a scope and import variables from a scope, /// exec Python statements in the scope then discard it. /// [Test] public void TestImportAllFromScope() { using (Py.GIL()) { ps.Set("bb", 100); ps.Set("cc", 10); using (var scope = ps.NewScope()) { scope.Exec("aa = bb + cc + 3"); var result = scope.Get("aa"); Assert.AreEqual(113, result); } Assert.IsFalse(ps.Contains("aa")); } } /// /// Create a scope and import variables from a scope, /// call the function imported. /// [Test] public void TestImportScopeFunction() { using (Py.GIL()) { ps.Set("bb", 100); ps.Set("cc", 10); ps.Exec( "def func1():\n" + " return cc + bb\n"); using (PyScope scope = ps.NewScope()) { //'func1' is imported from the origion scope scope.Exec( "def func2():\n" + " return func1() - cc - bb\n"); dynamic func2 = scope.Get("func2"); var result1 = func2().As(); Assert.AreEqual(0, result1); scope.Set("cc", 20);//it has no effect on the globals of 'func1' var result2 = func2().As(); Assert.AreEqual(-10, result2); scope.Set("cc", 10); //rollback ps.Set("cc", 20); var result3 = func2().As(); Assert.AreEqual(10, result3); ps.Set("cc", 10); //rollback } } } /// /// Import a python module into the session with a new name. /// Equivalent to the Python "import .. as .." statement. /// [Test] public void TestImportScopeByName() { using (Py.GIL()) { ps.Set("bb", 100); using (var scope = Py.CreateScope()) { scope.ImportAll("test"); //scope.ImportModule("test"); Assert.IsTrue(scope.Contains("bb")); } } } /// /// Use the locals() and globals() method just like in python module /// [Test] public void TestVariables() { (ps.Variables() as dynamic)["ee"] = new PyInt(200); var a0 = ps.Get("ee"); Assert.AreEqual(200, a0); ps.Exec("locals()['ee'] = 210"); var a1 = ps.Get("ee"); Assert.AreEqual(210, a1); ps.Exec("globals()['ee'] = 220"); var a2 = ps.Get("ee"); Assert.AreEqual(220, a2); using (var item = ps.Variables()) { item["ee"] = new PyInt(230); } var a3 = ps.Get("ee"); Assert.AreEqual(230, a3); } /// /// Share a pyscope by multiple threads. /// [Test] public void TestThread() { //After the proposal here https://github.com/pythonnet/pythonnet/pull/419 complished, //the BeginAllowThreads statement blow and the last EndAllowThreads statement //should be removed. dynamic _ps = ps; var ts = PythonEngine.BeginAllowThreads(); using (Py.GIL()) { _ps.res = 0; _ps.bb = 100; _ps.th_cnt = 0; //add function to the scope //can be call many times, more efficient than ast ps.Exec( "def update():\n" + " global res, th_cnt\n" + " res += bb + 1\n" + " th_cnt += 1\n" ); } int th_cnt = 3; for (int i =0; i< th_cnt; i++) { System.Threading.Thread th = new System.Threading.Thread(()=> { using (Py.GIL()) { //ps.GetVariable("update")(); //call the scope function dynamicly _ps.update(); } }); th.Start(); } //equivalent to Thread.Join, make the main thread join the GIL competition int cnt = 0; while(cnt != th_cnt) { using (Py.GIL()) { cnt = ps.Get("th_cnt"); } System.Threading.Thread.Sleep(10); } using (Py.GIL()) { var result = ps.Get("res"); Assert.AreEqual(101* th_cnt, result); } PythonEngine.EndAllowThreads(ts); } } }
X Tutup