Embedding Python in C# via resources - c#

I have been working on a problem for a while now which I cannot seem to resolve so I need some help! The problem is that I am writing a program in C# but I require a function from a Python file I created. This in itself is no problem:
...Usual Stuff
using IronPython.Hosting;
using IronPython.Runtime;
using Microsoft.Scripting;
using Microsoft.Scripting.Hosting;
namespace Program
{
public partial class Form1 : Form
{
Microsoft.Scripting.Hosting.ScriptEngine py;
Microsoft.Scripting.Hosting.ScriptScope s;
public Form1()
{
InitializeComponent();
py = Python.CreateEngine(); // allow us to run ironpython programs
s = py.CreateScope(); // you need this to get the variables
}
private void doPython()
{
//Step 1:
//Creating a new script runtime
var ironPythonRuntime = Python.CreateRuntime();
//Step 2:
//Load the Iron Python file/script into the memory
//Should be resolve at runtime
dynamic loadIPython = ironPythonRuntime.;
//Step 3:
//Invoke the method and print the result
double n = loadIPython.add(100, 200);
numericUpDown1.Value = (decimal)n;
}
}
}
However, this requires for the file 'first.py' to be wherever the program is once compiled. So if I wanted to share my program I would have to send both the executable and the python files which is very inconvenient. One way I thought to resolve this is by adding the 'first.py' file to the resources and running from there... but I don't know how to do this or even if it is possible.
Naturally the above code will not work for this as .UseFile method takes string arguments not byte[]. Does anyone know how I may progress?

Lets start with the simplest thing that could possibly work, you've got some code that looks a little like the following:
// ...
py = Python.CreateEngine(); // allow us to run ironpython programs
s = py.CreateScope(); // you need this to get the variables
var ironPythonRuntime = Python.CreateRuntime();
var x = py.CreateScriptSourceFromFile("SomeCode.py");
x.Execute(s);
var myFoo = s.GetVariable("myFoo");
var n = (double)myFoo.add(100, 200);
// ...
and we'd like to replace the line var x = py.CreateScriptSourceFromFile(... with something else; If we could get the embedded resource as a string, we could use ScriptingEngine.CreateScriptSourceFromString().
Cribbing this fine answer, we can get something that looks a bit like this:
string pySrc;
var resourceName = "ConsoleApplication1.SomeCode.py";
using (var stream = System.Reflection.Assembly.GetExecutingAssembly()
.GetManifestResourceStream(resourceName))
using (var reader = new System.IO.StreamReader(stream))
{
pySrc = reader.ReadToEnd();
}
var x = py.CreateScriptSourceFromString(pySrc);

Related

How to properly setup CodeContext of IronPython to directly invoke IO from C#?

I am trying to directly invoke IronPython's built-in modules from C#. It looks like I'm missing some important initialization, that I can't find anywhere in the code.
Here's what I do:
namespace py.consoleio
{
using IronPython.Runtime;
using Microsoft.Scripting.Hosting;
using Microsoft.Scripting.Hosting.Providers;
using Microsoft.Scripting.Runtime;
public static class consoleio
{
public static string name;
static void Main()
{
var setup = new ScriptRuntimeSetup();
setup.LanguageSetups.Add(
IronPython.Hosting.Python.CreateLanguageSetup(null));
var dlrRuntime = new ScriptRuntime(setup);
var scriptDomainManager = HostingHelpers.GetDomainManager(dlrRuntime);
var pythonContext = new PythonContext(scriptDomainManager, null);
var context = new CodeContext(new PythonDictionary(), new ModuleContext(new PythonDictionary(), DefaultContext.DefaultPythonContext));
name = IronPython.Modules.Builtin.input(context, "What is your name?\n");
IronPython.Modules.Builtin.print(context, "Hi, %s.", consoleio.name);
System.GC.KeepAlive(pythonContext);
}
}
}
That properly outputs "What is your name?", but then crashes trying to decode input: unknown encoding: cp437.
Now I've already found, that encodings are initialized in Src/StdLib/Lib/encodings/init.py
I can't find how it gets to loading this module in a normal IronPython run (e.g. a console host), so I can't reproduce it in C# program.
My goal here is to invoke IronPython functions without dynamic dispatch.
UPD. Now I also tried to do this:
var engine = Python.CreateEngine();
this.ScriptDomainManager = HostingHelpers.GetDomainManager(engine.Runtime);
to the same result
Figured that one out: encodings module is implemented in Python in IronPython (core modules are in C#). It always worked with IronPythonConsole project, because it implicitly adds IronPython source for standard libraries to Python path. I just had to explicitly specify path like this:
var options = new Dictionary<string, object> { ["SearchPaths"] = path };
var engine = Python.CreateEngine(options);

DLR: Do i really need code generation here?

spent some time again with the scripting interface of my app.
i guess i now have an advanced dlr problem here.
I have a python script
I have an .NET object [o1]
I call a method on the python script from .NET via Iron Python.
The python code creates an object [o2]
The python code calls an method on object [o1] passing [o2] as an argument (Via subclassing DynamicMetaObject)
In the .NET code of the o1-method i want to dynamically call methods on o2
For example i could do that via
((dynamic)o2).FuncInPythonScript
so far so good thats all working.
.NET calls Python (step 3)
Python calls back .NET (step 5)
So i have a basic biderectional control flow between .NET and Python.
We go further:
In the [o1]-method I use LanguageContext.GetMemberNames on [o2]
I wanna call these members somehow via reflection or expressions.
Meaning i dont wanna use the dynamic keyword as in step 7.
Instead somehow call the methods via reflection.
Problem is:
a) I do not know how to get the RuntimeType of the Python-Type, meaning i have no System.Reflection.MethodInfo so i stuck here
b) I try to use LanguageContext.CreateCallBinder and MetaObject.BindInvokeMember so i should have the method 'FuncInPythonScript' bound
But then i'm stuck in how to finally call the bound method.
I see i could use code generation to just generate the code as in step 7, just with the member names from step 8.
But is that really necessary?
I do not see wether approach a) or b) might work or maybe there is somthing i did not think of.
Please do not answer with basic "How do i invoke a python method from .NET" hints.
That is done in steps 1-7 and i have no problem doing this. It's really an advanced problem.
namespace DynamicMetaObjectTest
{
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.IO;
using System.Dynamic;
using System.Linq.Expressions;
using Microsoft.Scripting.Hosting;
using Microsoft.Scripting.Hosting.Providers;
class Program
{
internal sealed class CDotNetObject : IDynamicMetaObjectProvider
{
DynamicMetaObject IDynamicMetaObjectProvider.GetMetaObject(Expression aExp)
{
return new CInvoker(this, aExp);
}
private sealed class CInvoker : DynamicMetaObject
{
internal CInvoker(CDotNetObject aGws, Expression aExp) : base(aExp, BindingRestrictions.Empty, aGws)
{
this.DotNetObject = aGws;
}
private readonly CDotNetObject DotNetObject;
public override DynamicMetaObject BindGetMember(GetMemberBinder binder)
{
var aMethodInfo = this.GetType().GetMethod("GetSetResultDelegate");
var aExp = Expression.Call(Expression.Constant(this), aMethodInfo);
var aRestrictions = BindingRestrictions.GetTypeRestriction(this.Expression, this.LimitType);
var aMetaObject = new DynamicMetaObject(aExp, aRestrictions);
return aMetaObject;
}
public Action<object> GetSetResultDelegate()
{
return this.DotNetObject.SetResultProvider;
}
}
public void SetResultProvider(object aPythonObject_O2)
{
var aResult = ((dynamic)aPythonObject_O2).GetResult(); // this is for noobs. ;-)
var aMetaObjectProvider = (IDynamicMetaObjectProvider)aPythonObject_O2;
var aMetaObject = aMetaObjectProvider.GetMetaObject(Expression.Constant(aPythonObject_O2));
var aLanguageContext = HostingHelpers.GetLanguageContext(gScriptEngine);
var aMemberNames = aLanguageContext.GetMemberNames(aPythonObject_O2);
var aNonSystemMembers = from aMemberName in aMemberNames where !aMemberName.StartsWith("__") select aMemberName;
foreach (var aMemberName in aNonSystemMembers)
{
Console.WriteLine("Getting function result from Python script: " + aMemberName);
// Now problem:
// P1) How to determine wether its an function or an member variable?
// P2) How to invoke the method respectively get the value of the member variable?
// Your turn ;-)
// some of my failures:
{ // does not work:
//var aVar1Binder = aLanguageContext.CreateGetMemberBinder("GetVar1", false);
//var aVar1Bound = aMetaObject.BindGetMember(aVar1Binder);
//var aCallInfo = new CallInfo(0 , new string[]{});
//var aInvokeBinder = aLanguageContext.CreateCallBinder("GetVar1", false, aCallInfo);
//var aInvokeBound = aMetaObject.BindInvokeMember(aInvokeBinder, new DynamicMetaObject[]{ aVar1Bound});
////var aInvokeExp = Expression.Invoke(Expression.Constant(aInvokeBound), new Expression[] { });
}
{ // does not work
//var aExpandable = (IronPython.Runtime.Binding.IPythonExpandable)aMetaObject;
}
}
}
}
static ScriptEngine gScriptEngine;
static void Main(string[] args)
{
var aScriptRuntime = IronPython.Hosting.Python.CreateRuntime();
// That's the python script from step 1:
var aCode = "class CustomView(object) :" + Environment.NewLine +
"\tdef GetResult(self) :" + Environment.NewLine +
"\t\treturn 42;" + Environment.NewLine + // cuz 42 is the answer to everything ;-)
"DotNetObject.SetResultProvider(CustomView())";
var aEngine = aScriptRuntime.GetEngine("py");
gScriptEngine = aEngine;
var aScope = aEngine.CreateScope();
var aDotNetObject = new CDotNetObject();
aScope.SetVariable("DotNetObject", aDotNetObject);
// That's the invoke to pything from step 3:
aEngine.Execute(aCode, aScope);
}
}
}

Getting a SemanticModel of a cshtml file?

I'd like to use Roslyn to analyze semantic information within the context of a block of C# code inside a Razor View.
Is there any way (within Visual Studio 2015, or even in a unit test) to get the SemanticModel that represents this code?
Razor files contain a C# projection buffer with the generated C# code (including the parts that you don't write yourself). This buffer has full Roslyn services and is exactly what you're looking for.
You need to walk through the TextView's BufferGraph and find the CSharp buffer; you can then get its Document and semantic model.
If you're starting from the cursor location, you need simply need to map that location to a CSharp buffer.
Note that it is perfectly legal for a TextView to contain multiple CSharp buffers. (although the Razor editor will never do that)
If you aren't working in a TextView, you need to do all of this yourself; you need to run the Razor source through the Razor compiler to get the generated C# source, then compile that with Roslyn to get a semantic model.
Extract the code representing the view from the Razor view file using RazorTemplateEngine.GenerateCode and CSharpCodeProvider.GenerateCodeFromCompileUnit (or the VBCodeProvider if you want the intermediate source as VB.NET). You can then use Roslyn to parse the code.
There's an example of using Roslyn with Razor view files here.
Take note that GenerateCode carries a caveat:
This type/member supports the .NET Framework infrastructure and is not intended to be used directly from your code.
Just in case anyone else gets stuck on this, I have mini sample app which may help.
I had a CMS class like this:
public partial class CMS
{
public static string SomeKey
{
get { return (string) ResourceProvider.GetResource("some_key"); }
}
// ... and many more ...
}
... and I wanted to find out which of these were used throughout my solution for a report ... Enter Roslyn!
The following app will print out the count for the used and unused references:
using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.FindSymbols;
using Microsoft.CodeAnalysis.MSBuild;
using Microsoft.CSharp;
using System;
using System.CodeDom.Compiler;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Web.Razor;
namespace TranslationSniffer
{
class Program
{
static void Main(string[] args)
{
new Program().Go().Wait();
}
public async Task Go()
{
// Roslyn!
var ws = MSBuildWorkspace.Create();
// Store the translation keys...
List<string> used = new List<string>();
List<string> delete = new List<string>();
string solutionRoot = #"C:\_Code\PathToProject\";
string sln = solutionRoot + "MySolution.sln";
// Load the solution, and find all the cshtml Razor views...
var solution = await ws.OpenSolutionAsync(sln);
var mainProj = solution.Projects.Where(x => x.Name == "ConsumerWeb").Single();
FileInfo[] cshtmls = new DirectoryInfo(solutionRoot).GetFiles("*.cshtml", SearchOption.AllDirectories);
// Go through each Razor View - generate the equivalent CS and add to the project for compilation.
var host = new RazorEngineHost(RazorCodeLanguage.Languages["cshtml"]);
var razor = new RazorTemplateEngine(host);
var cs = new CSharpCodeProvider();
var csOptions = new CodeGeneratorOptions();
foreach (var cshtml in cshtmls)
{
using (StreamReader re = new StreamReader(cshtml.FullName))
{
try
{
// Let Razor do it's thang...
var compileUnit = razor.GenerateCode(re).GeneratedCode;
// Pull the code into a stringbuilder, and append to the main project:
StringBuilder sb = new StringBuilder();
using (StringWriter rw = new StringWriter(sb))
{
cs.GenerateCodeFromCompileUnit(compileUnit, rw, csOptions);
}
// Get the new immutable project
var doc = mainProj.AddDocument(cshtml.Name + ".cs", sb.ToString());
mainProj = doc.Project;
}
catch(Exception ex)
{
Console.WriteLine("Compile fail for: {0}", cshtml.Name);
// throw;
}
continue;
}
}
// We now have a new immutable solution, as we have changed the project instance...
solution = mainProj.Solution;
// Pull out our application translation list (its in a static class called 'CMS'):
var mainCompile = await mainProj.GetCompilationAsync();
var mainModel = mainCompile.GetTypeByMetadataName("Resources.CMS");
var translations = mainModel.GetMembers().Where(x => x.Kind == SymbolKind.Property).ToList();
foreach (var translation in translations)
{
var references = await SymbolFinder.FindReferencesAsync(translation, solution) ;
if (!references.First().Locations.Any())
{
Console.WriteLine("{0} translation is not used!", translation.Name);
delete.Add(translation.Name);
}
else
{
Console.WriteLine("{0} :in: {1}", translation.Name, references.First().Locations.First().Document.Name);
used.Add(translation.Name);
}
}
Console.WriteLine();
Console.WriteLine("Used references {0}. Unused references: {1}", used.Count, delete.Count);
return;
}
}
}
Roslyn only models cshtml files while they are open, but during that time they are similar to every other source file in the Workspace model.
Is there something specific you have tried that isn't working?

Looking for Hello World program for Solr.NET in C#

I have Solr server running (on Linux box, not that it matter), it is loaded with 2M documents and search works fine in Java.
I need however to write C# (client) program to query it. I downloaded Solr.NET but I am confused what to begin with. Solutions included with it do not compile, and browsing through C# it does not look like the program is doing what I need to do.
Does anyone have a sort of Hello World program for Solr.NET in C#? Below I will publish Java version of what I and looking for, C# version anyone? Oh, and please, what minimum set of assemblies do I need to include into such simple client program? Thank you
import org.apache.solr.client.solrj.SolrQuery;
import org.apache.solr.client.solrj.SolrServer;
import org.apache.solr.client.solrj.impl.HttpSolrServer;
import org.apache.solr.client.solrj.response.QueryResponse;
import org.apache.solr.common.SolrDocumentList;
public class SolrHeloWorld // Java
{
public static void main(String[] args)
{
// Connect to server
SolrServer solr = new HttpSolrServer ("http://192.168.1.211:8983/solr/collection1");
// Query for search term 'banana'
SolrQuery query = new SolrQuery();
query.setQuery("banana");
query.setStart(0);
query.setRows(50);
query.set("defType", "edismax");
try
{
QueryResponse response = solr.query(query);
// Print results
SolrDocumentList results = response.getResults();
for (int i = 0; i < results.size(); i++)
{
System.out.println(results.get(i));
}
}
catch (Exception e)
{
System.out.println("Error: " + e.getMessage());
}
}
}
As suggested I have take another closer look at documentation for Solr.NET. Still, I wasn’t able to figure out which assemblies are missing in solutions that came with download so they still do not compile! More importantly it does not appear that you can write bare bone program that simply prints JSON without NHibernate, defining class mapping and all that.
Never the less, it is not that hard to write simple Hello World client program in C# that queries Solr. And it does not require Solr.NET at all! Here is the one that uses HttpWebRequest and JSON serializer/deserializer to simply print JSON of all documents returned by query
using System;
using System.Net;
using System.IO;
using System.Web.Script.Serialization; // Require adding System.Web.Extentions.dll
class SolrHeloWorld // C#
{
static void Main()
{
Uri uri = new Uri("http://192.168.1.211:8983/solr/collection1/select?q=banana&start=0&rows=50&wt=json&indent=true&defType=edismax");
WebRequest request = HttpWebRequest.Create(uri);
request.Method = WebRequestMethods.Http.Get;
WebResponse response = request.GetResponse();
StreamReader reader = new StreamReader(response.GetResponseStream());
string jsonResponse = reader.ReadToEnd();
response.Close();
JavaScriptSerializer serializer = new JavaScriptSerializer();
dynamic jsonObject = serializer.Deserialize<dynamic>(jsonResponse);
dynamic dd = jsonObject["response"]["docs"];
Object[] results = (Object[])dd;
foreach (Object res in results)
{
Console.WriteLine(serializer.Serialize(res));
}
}
}
There is a course in Pluralsight that gets you started with Solr and SolrNet. The last module is about SolrNet specifically:
http://www.pluralsight.com/courses/enterprise-search-using-apache-solr

Embedding IronPython in C#

I am just looking into using IronPython with C# and cannot seem to find any great documentation for what I need. Basically I am trying to call methods from a .py file into a C# program.
I have the following which opens the module:
var ipy = Python.CreateRuntime();
var test = ipy.UseFile("C:\\Users\\ktrg317\\Desktop\\Test.py");
But, I am unsure from here how to get access to the method inside there. The example I have seen uses the dynamic keyword, however, at work I am only on C# 3.0.
Thanks.
See embedding on the Voidspace site.
An example there, The IronPython Calculator and the Evaluator
works over a simple python expression evaluator called from a C# program.
public string calculate(string input)
{
try
{
ScriptSource source =
engine.CreateScriptSourceFromString(input,
SourceCodeKind.Expression);
object result = source.Execute(scope);
return result.ToString();
}
catch (Exception ex)
{
return "Error";
}
}
You can try use the following code,
ScriptSource script;
script = eng.CreateScriptSourceFromFile(path);
CompiledCode code = script.Compile();
ScriptScope scope = engine.CreateScope();
code.Execute(scope);
It's from this article.
Or, if you prefer to invoke a method you can use something like this,
using (IronPython.Hosting.PythonEngine engine = new IronPython.Hosting.PythonEngine())
{
engine.Execute(#"
def foo(a, b):
return a+b*2");
// (1) Retrieve the function
IronPython.Runtime.Calls.ICallable foo = (IronPython.Runtime.Calls.ICallable)engine.Evaluate("foo");
// (2) Apply function
object result = foo.Call(3, 25);
}
This example is from here.

Categories

Resources