I'm attempting to call a C# function from a Python script, via the clr module from the PythonNet library.
One of the arguments that this C# function takes is of the type System.Collections.Generic.IEnumerable. Simply supplying a list of the required data types to the first argument results in a 'list' value cannot be converted to 'System.Collections.Generic.IEnumerable' error.
After searching online, the supposed .NET datatypes should already be included in the Python installation, and I should be able to access them. However, I'm unsure as to how.
Doing:
from System.Collections.Generic import *
Fails because the module isn't found, while doing:
import collections
Doesn't have a namespace IEnumerable.
How would I go about converting a Python list to the System.Collections.Generic.IEnumerable data type?
Thanks for reading my post, any guidance is appreciated.
Before importing anything from C#/.NET you have to import clr from pythonnet package.
After messing around in the Python script for a few hours, I managed to figure out a solution:
First, the actual C# Collections namespace has to be imported via the clr module as such:
clr.AddReference("System.Collections")
Then, the specific data type of the Collections namespace has to be imported:
from System.Collections.Generic import IEnumerable
And then one should be able to use the respective data type, and call all the class functions it has. In my case, I wanted to convert a Python List into the IEnumerable datatype. Therefore, I could iterate over my Python List, and call the Add function of the IEnumerable class (using datatype of int as an example):
myList = [1, 2, 3]
myIEnumerable = IEnumerable[int]()
for i in range(len(myList)):
myIEnumerable.Add(myList[i])
As a sidenote, while the C# function that I wanted to call from my Python script has one of its arguments listed as accepting a type of System.Collections.Generic.IEnumerable, I managed to get it to work with having a System.Collections.Generic.List type instead. Perhaps it'll be useful for someone else.
Related
Is there a way to perform a python import which is not atomic?
For instance, I have a file as follows:
# Filename: a.py
myvariable = 1
mylist = [1, 2, 3]
raise ImportError
donotimportthis = 5
I then have a separate file which does the following:
import a
a.myvariable == 1 # This is okay as it imported it
a.donotimportthis # <-- raise an exception as this is not imported.
I have a file which contains some python code, this follows the format of:
...variables...
import X
I do not have X installed nor do I want it however I do want the variables.
Note: This file is autogenerated not by me but by a tool whose version is frozen.
Two choices, in descending order of preference:
Change the autogeneration process. Instead of invoking proprietary_autogen_process, invoke custom_autogen_wrapper. This wrapper in turn first invokes the proprietary third-party tool, and then modifies the produced module source code by searching for the code that imports module X, and deletes everything after it.
This is relatively straightforward. You just need to take some care to not introduce false positives or false negatives by performing too loose (or too strict) matching of the import code. Ideally you’d use an AST rewriter but that’s probably overkill; a regular expression search for import X might work, although it will yield wrong results if this text appears inside a comment, string literal or inside a method which isn’t executed.
Generate a stub module X in a location where it will be found by the autogenerated module when importing the latter. I don’t recommend this because it’s tedious: You probably can’t just generate an empty module, since the autogenerated module will want to use X. You need to generate meaningful method stubs.
You can do specific imports with
from a import myvariable
EDIT: The above won't work if anything that is flat in the file raises an error. If you have no way to edit the imported file then I don't know if there is a (resonable) solution to this. Sorry didn't realise.
(an unreasonable solution would be to read in the file as text, slice it, and then run eval on it).
Or, as mentioned in the comments, put the stuff you don't want under
if __name__=="__main__":
<here>
Then it will only be invoked if you run the file directly.
What you can do is removing the donotimportthis variable at the end of the module, as follows: del donotimportthis. I hope it helps
I am writing a python3 + webkit2 + gtk3 based GUI. Everything works fine, but when I tried to use WebKit2.WebView.run_javascript_finish() in a callback function, getting the return (a WebKit2.JavascriptResult objetc), e extrat the value with WebKit2.JavascriptResult.get_value(), I received a "TypeError: Couldn't find foreign struct converter for 'JavaScriptCore.Value'".
I have a "from gi.repository import JavaScriptCore" on the imports, and I dont know why this error is occuring.
ps: Sorry about my terrible english.
Unfortunately, using the JavaScriptCore library isn't supported in Python.
The definitions in gi.repository.JavaScriptCore only include opaque definitions for JavaScriptCore.Value and JavaScriptCore.GlobalContext in order to provide type information for functions that use those types; as you can verify by looking in /usr/share/gir-1.0/JavaScriptCore-4.0.gir. But as you've discovered, you can't actually call those functions because there's no information on how to convert those types to native Python objects.
I recommend writing a function in C which takes in your WebKit2.JavaScriptResult and fetches whatever information you need from it, and then exporting that function in its own private GIR library. So you would not use any JavaScriptCore types in your Python code. This is what it might look like:
from gi.repository import MyAppPrivate
# ...
def on_javascript_finish(obj, res):
result = obj.run_javascript_finish(res)
my_real_results = MyAppPrivate.process(result)
I would like to invoke the following python script in C :
#!/usr/bin/python2.7
import parser
def evaluate(text):
code = parser.expr(text).compile()
return eval(code)
as explained in the following page https://docs.python.org/2/extending/embedding.html, i can call this script from C using the pwd(path) of the file.
However, i would like to know if it's possible to not load the script by calling python on a C string directly, defining the script.
For example, i would like to let's say i put :
#define PYTHON_SCRIPT ((char*)(\
import parser\
\
def evaluate(text):\
code = parser.expr(text).compile()\
return eval(code)\
))
is it possible to call the python interpreter directly on that string?
Indeed, knowing that i need to pass text as a variable, i can't use this Pyrun_SimpleString function, and i was not able to find something to answer this question.
As mentioned in the comment there is no Pyrun_SimpleString. How to execute Python functions from C is covered here. One way to do it:
Compile your script using Py_CompileString
Create a dictionary for globals/locals.
Extract the function from your globals dict by using PyDict_GetItemString(name)
Build your arguments tuple with PyArg_ParseTuple
Execute your function object by using PyObject_CallFunction.
Take a look at Weave, it allows you to include C code directly in Python code.
I am using iPython in command prompt, Windows 7.
I thought this would be easy to find, I searched and found directions on how to use the inspect package but it seems like the inspect package is meant to be used for functions that are created by the programmer rather than functions that are part of a package.
My main goal to to be able to use the help files from within command prompt of iPython, to be able to look up a function such as csv.reader() and figure out all the possible arguments for it AND all possible values for these arguements.
In R programming this would simply be args(csv.reader())
I have tried googling this but they all point me to the inspect package, perhaps I'm misunderstanding it's use?
For example,
If I wanted to see a list of all possible arguments and the corresponding possible values for these arguments for the csv.reader() function (from the import csv package), how would I go about doing that?
I've tried doing help(csv.reader) but this doesn't provide me a list of all possible arguments and their potential values. 'Dialect' shows up but it doesn't tell me the possible values of the dialect argument of the csv.reader function.
I can easily go to the site: https://docs.python.org/3/library/csv.html#csv-fmt-params and see that the dialect options are: delimiter, doublequote, escapechar, etc.. etc..but is there a way to see this in Python console?
I've also tried dir(csv.reader) but this isn't what I was looking for either.
Going bald trying to figure this out....
There is no way to do this generically, help(<function>) will at a minimum return you the function signature (including the argument names), Python is dynamically typed so you don't get any types and arguments by themselves don't tell you what the valid values are. This is where a good docstring comes in.
However, the csv module does have a specific function for listing the dialects:
>>> csv.list_dialects()
['excel', 'excel-tab', 'unix']
>>> help(csv.excel)
Help on class excel in module csv:
class excel(Dialect)
| Describe the usual properties of Excel-generated CSV files.
...
The inspect module is extremely powerful. To get a list of classes, for example in the csv module, you could go:
import inspect, csv
from pprint import pprint
module = csv
mod_string = 'csv'
module_classes = inspect.getmembers(module, inspect.isclass)
for i in range(len(module_classes)):
myclass = module_classes[i][0]
myclass = mod_string+'.'+myclass
myclass = eval(myclass)
# could construct whatever query you want about this class here...
# you'll need to play with this line to get what you want; it will failasis
#line = inspect.formatargspect(*inspect.getfullargspec(myclass))
pprint(myclass)
Hope this helps get you started!
I'm writing an interpreter for an old in-game scripting language, and so need to compile dictionary that has the name of the command from the language matched up against the symbol for that function.
Now, I've already figured out here: How to call a function based on list entry?
...That you can call functions this way, and I know that you can use dir to get a list of strings of all functions in a module. I've been able to get this list, and using a regex, removed the built-in commands and anything else I don't actually want the script to be able to call. The goal is to sandbox here. :)
Now that I have the list of items that are defined in the module, I need to get the symbol for each definition.
For a more visual representation, this is the test module I want to get the symbol for:
def notify(stack,mufenv):
print stack[-1]
It's pulled in via an init script, and I am able to get the notify function's name in a list using:
import mufprims
import re
moddefs=dir(mufprims)
primsfilter=re.compile('__.+__')
primslist=[ 'mufprims.' + x for x in dir(mufprims) if not primsfilter.match(x) ]
print primslist
This returns:
['mufprims.notify']
...which is the exact name of the function I wish to find the symbol for.
I read over http://docs.python.org/library/symtable.html here, but I'm not sure I understand it. I think this is the key to what I want, but I didn't see an example that I could understand. Any ideas how I would get the symbol for the functions I've pulled from the list?
You want to get the function from the mufprims module by using getattr and the function name. Like so:
primslist=[getattr(mufprims, x) for x in dir(mufprims) if not primsfilter.match(x) ]
I thought I might add another possible suggestion for retrieving the functions of an object:
import inspect
# example using os.path
import os.path
results = inspect.getmembers(os.path, inspect.isroutine)
print results
# truncated result
[...,
('splitdrive', <function splitdrive at 0x1002bcb18>),
('splitext', <function splitext at 0x1002bcb90>),
('walk', <function walk at 0x1002bda28>)]
Using dir on the object would essentially give you every member of that object, including non-callable attributes, etc. You could use the inspect module to get a more controlled return type.