Using NLTK in C# via IronPython - c#

I'm using Visual Studio 2010. I have an IronPython console project and a C# console project. This IronPython script works fine when I run it by itself:
import nltk
def Simple():
baconIpsumFile = open('baconipsum.txt', 'r')
baconIpsumCorpus = baconIpsumFile.read()
tokens = nltk.word_tokenize(baconIpsumCorpus)
text = nltk.Text(tokens)
print text
Here is the C# console program, which does not work fine:
using IronPython.Hosting;
namespace IronNLTK.CSharp.Console
{
class Program
{
static void Main(string[] args)
{
var ipy = Python.CreateRuntime();
dynamic test = ipy.UseFile("C:\\Path\\To\\Program.py");
test.Simple();
}
}
}
I get an ImportException: No module named nltk. What am I missing?

sounds like you need to update sys.path to point to wherever NLTK lives.
check this out: Importing external module in IronPython

Awesome news, Visual Studio 2017 is embedded with Anaconda’s Python distribution which has NTLK and other machine learning packages.

Related

code completion / language server for embedded IronPython scripts

I have an application that exposes some c# objects to an embedded IronPython interpreter like this:
using IronPython.Hosting;
namespace ironpy
{
public class Foo
{
public void bar(string message)
{
System.Console.WriteLine(message);
}
}
class Program
{
static void Main(string[] args)
{
var engine = Python.CreateEngine();
var scope = engine.CreateScope();
var test = new Foo();
scope.SetVariable("foo", test);
string code = "foo.bar('Hello')";
engine.Execute(code, scope);
}
}
}
In practice the python source code comes from an textfile loaded at runtime.
When editing such a source file in VSCode or other editors the language server that provides code completion obviously doesn't have any idea about whats going to be available. So you have no code completion and annoying error squiggles everywhere.
Is it somehow possible to write some sort of plugin/hint/linting file for one of the commonly used language servers to tell them about the exported C# API to get working code completion when editing the python source files?
I found the solution to my problem in the meantime: IronPython Stubs files
https://github.com/gtalarico/ironpython-stubs
In my opinion, defining .py file and implementing codes inside on it is the best way. Then you can execute your .py file like below;
https://stackoverflow.com/a/11779234/4582992

Intellisense for custom .net dll in visual studio code

I am trying to call a python script (SamplePython.py) from a C# console application using IronPython. When I run my console application, the script executes successfully and results are as expected. However I am not sure how I can add intellisense and auto complete for the custom .net types used in my script.
I tried importing python clr and calling clr.AddReference("customdll") but it did not provide any sought of intellisense.
Code Snippet of C# console code
ScriptSource pythonScript;
ObjectOperations objectOperations;
ScriptScope scope;
ScriptEngine pythonEngine = Python.CreateEngine();
scope = pythonEngine.CreateScope();
objectOperations = pythonEngine.Operations;
pythonScript = pythonEngine.CreateScriptSourceFromFile(#"<Path to script File>/SamplePython.py");
pythonScript.Execute(scope);
dynamic pythonMethod = scope.GetVariable("PythonMethod");
PythonTestType pythonTestType = new PythonTestType();
pythonTestType.TestProp = 8;
int x = pythonMethod(pythonTestType);
Code Snippet of C# custom type.
namespace PythonTestLibrary
{
public class PythonTestType
{
public int TestProp { get; set; }
}
}
Code Snippet of python script.
def PythonMethod(pythonTestType):
return pythonTestType.TestProp
When writing my python script in visual studio code, I expect the IDE to list out "TestProp" when I type pythonTestType and then the dot operator as part of intellisense just like I get for other python inbuilt datatypes.

How to import a C# dll to python

i've got a third party c# dll which has been created in dot net 4.5 and has a platform target of x86. I would like to import this into a python script and I've started off with Rob Deary's answer here. However I can't get his example to work. I'm using python version 2.7.6 and I get an AttributeError as shown below.
File "C:\Python27\Lib\ctypes\__init__.py", line 378, in __getattr__
func = self.__getitem__(name)
File "C:\Python27\Lib\ctypes\__init__.py", line 383, in __getitem__
func = self._FuncPtr((name_or_ordinal, self))
AttributeError: function 'add' not found
Please note that I am aware of Ironpython and Python for dot net but I need to get this working specifically with C python. Here's my sample code which generates the custom c# library: ClassLibrary1.dll
using System;
using System.Runtime.InteropServices;
using RGiesecke.DllExport;
class Test
{
[DllExport("add", CallingConvention = CallingConvention.Cdecl)]
public static int TestExport(int a, int b)
{
return a + b;
}
}
And here's the python script that generates the error
import ctypes
lib = ctypes.cdll.LoadLibrary('ClassLibrary1.dll')
lib.add(3,5)
When I use the line below, this is the output i get. So at least I know that it is loading the dll, but i'm not sure why the function can't be found.
>>> lib.__dict__
{'_FuncPtr': <class 'ctypes._FuncPtr'>, '_handle': 254476288, '_name': 'ClassLibrary1.dll'}
>>>
Any help will be appreciated. Thanks
As the RGiesecke.DllExport documentation states, you need to target a specific architecture (x86 or x64) when building your code. Leaving it set to Any CPU (the default) will not work.

Pythonnet: how to use an embedded python intepreter?

I'm trying to use an embedded python interpreter from C# using pythonnet (the python3 compatible version found at https://github.com/renshawbay/pythonnet)
My interpreter is located in D:\src\scratch\TestPythonNet\TestPythonNet\PythonRuntime and has the "Lib" and "Libs" folder from the python distribution.
I've tested using the following code:
<!-- language: c# -->
PythonEngine.PythonHome = #"D:\src\scratch\TestPythonNet\TestPythonNet\PythonRuntime";
PythonEngine.ProgramName = "PythonRuntime";
PythonEngine.Initialize();
using (Py.GIL())
{
PythonEngine.RunSimpleString("print(1)");
}
But, it doesn't work. I get a "SystemError: PyEvalCodeEx: NULL globals". Everytime I try to get an object from python, the code fails.
What am I doing wrong?
I think I've found the answer. If I add a reference to the "clr" module provided by pythonnet, it does work
PythonEngine.PythonHome = #"D:\src\scratch\TestPythonNet\TestPythonNet\PythonRuntime";
PythonEngine.ProgramName = "PythonRuntime";
PythonEngine.Initialize();
// ==>
PyObject a = PythonEngine.ImportModule("clr");
using (Py.GIL())
{
PythonEngine.RunSimpleString("print(1)");
}

How to invoke C#/.NET namespace in IronPython?

I'm looking to replicate the following in IronPython and searching has so far been fruitless and/or disappointing.
namespace Groceries
{
public class ChocolateMilk : Milk
{
// Other stuff here
}
}
The idea would be that the compiled Python DLL will be loaded into a C# program through System.Reflection.Assembly.Load and a GetType("Groceries.ChocolateMilk") on the loaded DLL would not return null.
The most recent answer I was able to find was in 2008 and said that it was impossible without using the Hosting API - http://lists.ironpython.com/pipermail/users-ironpython.com/2008-October/008684.html.
Any suggestions on how to accomplish this would be greatly appreciated. Any conclusions that this is currently impossible to do via IronPython will also be appreciated, but less so.
I'm a bit confused on what you're asking here. Are you trying to instantiate that C# code in your IronPython modules? Or do you have the equivalent classes written in IronPython and you want to instantiate them in your C# code?
Based on the link you posted, I suppose you're going for the latter and have IronPython classes that you want instantiated in your C# code. The answer is, you cannot directly instantiate them. When you compile IronPython code to an assembly, you cannot use the types defined there with your regular .NET code since there is not a one-to-one mapping between IronPython classes and .NET classes. You would have to host the assembly in your C# project and instantiate it that way.
Consider this module, Groceries.py compiled to Groceries.dll residing in the working directory:
class Milk(object):
def __repr__(self):
return 'Milk()'
class ChocolateMilk(Milk):
def __repr__(self):
return 'ChocolateMilk()'
To host the module in your C# code:
using System;
using IronPython.Hosting;
using System.IO;
using System.Reflection;
class Program
{
static void Main(string[] args)
{
var engine = Python.CreateEngine();
var groceriesPath = Path.GetFullPath(#"Groceries.dll");
var groceriesAsm = Assembly.LoadFile(groceriesPath);
engine.Runtime.LoadAssembly(groceriesAsm);
dynamic groceries = engine.ImportModule("Groceries");
dynamic milk = groceries.ChocolateMilk();
Console.WriteLine(milk.__repr__()); // "ChocolateMilk()"
}
}
Otherwise to go the other way and create an instance of your .NET type in your IronPython code (as your title suggests). You'd need to add the path to your assembly, reference it, then you could instantiate it as needed.
# add to path
import sys
sys.path.append(r'C:\path\to\assembly\dir')
# reference the assembly
import clr
clr.AddReferenceToFile(r'Groceries.dll')
from Groceries import *
chocolate = ChocolateMilk()
print(chocolate)

Categories

Resources