How do I call Python scripts with packages from IronPython? - c#

How would I come to implementing a Python script that requires external modules (such as BeautifulSoup4 and requests) in my C# project? I want to call a function in the Python script but it keeps throwing me a "IronPython.Runtime.Exceptions.ImportException: 'No module named requests'".
I do not have any IronPython script written because I'm using a Python script that was made from another user. I have a virtual environment set up with Python to import the necessary modules.
I have no idea where to approach this. I've looked on multiple sites but they all require me to write an IronPython script. Are there no other options to calling functions other than setting up the necessary script?
C# Code:
static dynamic pythonFile;
static void Main(string[] args)
{
// Loading Python file
var ipy = Python.CreateRuntime();
pythonFile = ipy.UseFile("test.py"); //throws error when this launches.
DisplayMain();
Console.ReadKey();
}
Python Code (small snippet for example):
import requests
def get_stock(stock_name, price_metric):
print(stock_name + " " + price_metric)
def get_industry_indicators(startTime, endTime):
print(startTime + " " + endTime)
def get_market_cap(industry, startTime, endTime):
print(industry + " " + startTime + " " + endTime)
def get_headers(link):
print(requests.get(link))
I want to be able to call my python function (get_headers) and pass in a link and then have it print on my C# Console. Please help!

I found the error. Search paths for the needed modules must be included. Here is an example.
var engine = Python.CreateEngine();
var searchPaths = new List<string>();
searchPaths.Add(AppDomain.CurrentDomain.BaseDirectory + #"\Lib\site-packages");
searchPaths.Add(#"C:\...\projectName\Lib\");
engine.SetSearchPaths(searchPaths);
engine.ExecuteFile("test.py");

Related

Porting winform application to run on raspberry PI

I have a c# winform application that I want to port to run on my new Raspberry PI 3. I'm in moaning mode because I thought that my app would just run. That is not the case at all. My winform app uses quart. net, the aforge library and common .net libraries such as system.configuration.
I though I would start with my logging class as someone had mentioned that non UI code should be easy to convert if anything needed changing at all.
This looks like I'm going to have to reinvent the wheel. To be specific for startes have a look at the function below. Any code that uses system.configuration will not work.
Is there any easier way of getting my app to work or do I have to literally convert almost all my code. Is the aforge library even going to work on the PI?
Is quart.net going to work?
Right now I feel like giving up and buying a small windows PC that runs "proper" windows.
C# Winform Code
class Logging
{
public void Write_To_Log_File(String Message, String Procedure, String Error_Code, String Error_String)
{
try
{
// If the log file is bigger than allowed size then archive
if (File.Exists(#ConfigurationManager.AppSettings["LogSavePath"]))
{
FileInfo file = new FileInfo(#ConfigurationManager.AppSettings["LogSavePath"]);
if (file.Length > Convert.ToInt32(ConfigurationManager.AppSettings["FileLogSizeLimit"]))
{
// Rename the file
File.Move(#ConfigurationManager.AppSettings["LogSavePath"], #ConfigurationManager.AppSettings["LogSavePath"] + string.Format("{0:yyyy-MM-dd_hh-mm-ss-tt}", DateTime.Now) + ".csv");
}
}
// If log file does not exist then create it and add the headers
if (File.Exists(#ConfigurationManager.AppSettings["LogSavePath"]))
{
}
else
{
// Create the file
System.IO.File.Create("LogSavePath");
// Add data
string[] Headers = { "Time" + "," + "_Message" + "," + "Procedure" + "," + "Error_Code" + "," + "Error_String" };
System.IO.File.AppendAllLines(#ConfigurationManager.AppSettings["LogSavePath"], Headers);
}
if (File.Exists(#ConfigurationManager.AppSettings["LogSavePath"]))
{
string[] Log = { DateTime.Now.ToString() + "," + Message + "," + Procedure + "," + Error_Code + "," + Error_String };
System.IO.File.AppendAllLines(#ConfigurationManager.AppSettings["LogSavePath"], Log);
}
}
catch
{
}
}
}
Microsoft launched a Windows 10 IoT Core Porting Tool for this purpose. This can assist you in migrating from Win32 apps and libraries to Windows 10 IoT Core apps. More details here: https://developer.microsoft.com/en-us/windows/iot/win10/tools/iotapiportingtool

Sqlite C# code works in Unity Editor, but stops working after compiling

I run into the problem, that my Game works fine in the Unity 3d IDE, but the moment i compile it, it stops at a certain moment. In fact, when my sqlite code is executed. But not just at the initialization!
So this code runs just fine:
/// <summary>
/// Basic initialization of SQLite This will be activated by the manager script
/// </summary>
public static void SQLiteInit ()
{
string SQL_DB_LOCATION = #"URI=file:C:\temp\inlusio_data\InlusioDB.sqlite";
mConnection = new SqliteConnection(SQL_DB_LOCATION);
mCommand = mConnection.CreateCommand();
mConnection.Open();
ExecuteQuerry("PRAGMA page_size = " + "4096" + ";");
ExecuteQuerry("PRAGMA synchronous = " + "1" + ";");
mConnection.Close();
}
The ExecudeQuerry code seems to work fine, as the above part of my code worked. Here the ExecudeQuerry code:
public static void ExecuteQuerry (string sqlcomand)
{
Debug.Log(sqlcomand);
mCommand.CommandText = sqlcomand;
mCommand.ExecuteNonQuery();
}
problematic part, at which the game gets stuck:
public static void InitialSavingsToDB (string chiffre, string EasyDelay, string HardDealy, string session)
{
/// Subject code
ExecuteQuerry("INSERT INTO 'Subject'('Subject_Number','EasyDifficultyLevel','HardDifficultyLevel') VALUES ('" + chiffre + "','" + EasyDelay + "','" + HardDealy + "');");
}
I tried it like this, too :
public static void InitialSavingsToDB (string chiffre, string EasyDelay, string HardDealy, string session)
{
/// Subject code
mConnection.Open();
mCommand.CommandText = "INSERT INTO 'Subject'('Subject_Number','EasyDifficultyLevel','HardDifficultyLevel') VALUES ('" + chiffre + "','" + EasyDelay + "','" + HardDealy + "');";
mCommand.ExecuteNonQuery();
mConnection.Close();
}
It is maybe worth mentioning, that i call the InitialSavingsToDB function from my ManagerScript, that is declared as
public class ManagerScript : MonoBehaviour {
...
...
...
private void Start ()
{
...
testofsql.SQLiteInit(); // initialisation of the Data Base
...
...
...
}
...
...
}
So my code works fine, the data is saved perfectly when i test the Game from the Unity 3d Editor. The moment I compile it, it just does not continue ingame. No errors, nothing. I can even run around. But the game is stuck.
I honestly don`t knew how to solve this. Have googled since 2 weeks to make sqlite working in Unity, tried to avoid errors, debuged everything, till i found the source of the problem and am clueless ... i hope somebody can help.
Thank you very much!
Cheers,
petr
What is your the target platform? Android, IOS, ...?
Be aware, that for different platforms unity3d uses different sqlite assemblies.
Try to check the following project
https://github.com/codecoding/SQLite4Unity3d and compare data in Plugins folder with what is used in your project.
I would suggest trying to use a library designed for Unity. Personally this is what I have been doing to handle multi-platform SQLite handling. I would highly suggest this library/wrapper
SQLite made easy for Unity3d http://codecoding.github.io/SQLite4Unity3d
I am currently in the process of improving upon that and making it even more easy to work with. However this is probably a good starting point!
GOOD LUCK!

C/C++ Code Compiler in C#

In C#, I am able to compile VB and C# Code, using the code below, but I have no way of compiling C/C++ code. Is there any way of doing this?
C# Compiler:
public void Compile(string ToCompile)
{
string Result = null;
string errors = null;
Microsoft.CSharp.CSharpCodeProvider codeProvider = new Microsoft.CSharp.CSharpCodeProvider();
System.CodeDom.Compiler.ICodeCompiler icc = codeProvider.CreateCompiler();
string Output = #"mypath";
System.CodeDom.Compiler.CompilerParameters parameters = new System.CodeDom.Compiler.CompilerParameters();
parameters.GenerateExecutable = true;
parameters.OutputAssembly = Output;
System.CodeDom.Compiler.CompilerResults results = icc.CompileAssemblyFromSource(parameters, ToCompile);
if (ReturnErrors == true)
{
if (results.Errors.Count > 0)
{
foreach (System.CodeDom.Compiler.CompilerError CompErr in results.Errors)
{
errors +=
"Line number " + CompErr.Line +
", Error Number: " + CompErr.ErrorNumber +
", '" + CompErr.ErrorText + ";" +
Environment.NewLine + Environment.NewLine;
}
Result += "Errors have been found in your code: " + Environment.NewLine + errors;
}
else
{
Result += "Success!";
System.Diagnostics.Process.Start(Output);
}
}
And to create a VB compiler, I simply replace Microsoft.CSharp.CSharpCodeProvider codeProvider = new Microsoft.CSharp.CSharpCodeProvider(); with Microsoft.VisualBasic.VBCodeProvider codeProvider = new Microsoft.VisualBasic.VBCodeProvider();
You can compile c++/cli code, not native c++ as mentioned above.
You can archive c++/cli compilation with CppCodeProvider (http://msdn.microsoft.com/en-us/library/microsoft.visualc.cppcodeprovider(v=vs.85).aspx) class using it like in your example.
I'm assuming you've got a chunk of source, say containing a function with a known prototype, which you want to compile, and run within your currently running application.
In order to do this in native (not managed) C++, you'd need to do the following:
Dynamically store your code into a boilerplate dll source project (i.e. everything written with a gap for the function's code, which you'd insert)
Spawn a C++ compiler (which the end user would have to have pre-installed) to output a dll
Build up a C++/Cli wrapper that wraps the c++ dll that you built above, and compile that too (see Redwan's answer)
Dynamically load your wrapper Dll, and call the function.
If you can work with just managed c++/CLI, then Redwan's answer should be adequate on its own.

Calling PowerShell function from within the script in C# Application

I just started playing with PowerShell two days ago. I am running a PowerShell script form a C# console application. I pass in a list of objects (MyObj1) as a parameter to the script and do some data manipulation to the object. However, when I call a function within the script I get a function not recognized error while printing out the errors. Here is a small sample of what I am doing.
public class MyObj1
{
public string Property1 {get; set;}
public int Property2 {get; set;}
}
Here is part of code that I am using to run the script:
var rs = RunspaceFactory.CreateRunspace();
rs.Open();
rs.SessionStateProxy.SetVariable("list", myObjectList);
rs.SessionStateProxy.SetVariable("xml", xml);
var ps = PowerShell.Create();
ps.Runspace = rs;
var psScript = System.IO.File.ReadAllText(#"C:\temp\ps.ps1");
ps.AddScript(psScript);
ps.Invoke();
foreach (var item in myObjectList)
{
Console.WriteLine(item.Property1 + "; " + item.Property1);
}
Console.WriteLine("\n================================ ERRORS ============================ \n");
foreach (ErrorRecord err in ps.Streams.Error)
{
Console.WriteLine(err.ToString());
}
And here is the actual script:
$list | ForEach {
$_.Property1 = $_.GetType()
DoSomeThing ([ref] $_)
}
Function DoSomeThing ($MyObject)
{
$Asset.Property2 = $Asset.Property2 + $Asset.Property2
}
Two days ago while I was playing with same script using some dummy classes like above, I was able to modify the data but since this morning, I have modified the script to use real classes. And Ctrl+Z will only take me back to a certain point in my editor. In the ForEach loop everything works until I cal the function.
As for the project, the plan is to push this application with required data manipulation in C# and then have some optional changes done in the script. The point is to avoid push to the application to production server and handling all/most data manipulation in the script.
Move function declaration to the beginnig of the script file.
Function DoSomeThing ($MyObject)
{
$Asset.Property2 = $Asset.Property2 + $Asset.Property2
}
$list | ForEach {
$_.Property1 = $_.GetType()
DoSomeThing ([ref] $_)
}
PS doesn't compile script, it executes it command by command. So you have to create/declare function before you use it.

ResourceMap not found error when referencing a resource file within a portable class library

The problem I am facing has as follows:
I have developed a portable class library to encapsulate a service connection. Inside this class library there is a Resources.resw file containing strings. These strings are called only by methods of the class library (for example to override ToString() methods).
As I said this is a portable class library. If I reference it as a dll, or even as a project inside another solution, it gets built and compiles correctly. Then I make a call using a method of this library within my application, say
ClientFacadeConnector connector = new ClientFacadeConnector();
ICollection<SearchResult> results = null;
string message = string.Empty;
if (maxResults != -1) //Search with max Results
{
try
{
if (!contextQuery.Trim().Equals(string.Empty))
{
results = await connector.GetConnected().SearchAsync(contextQuery, query, maxResults);
message = "Search with ContextQuery " + contextQuery + ", Query " + query + ", max results " + maxResults.ToString();
}
else
{
results = await connector.GetConnected().SearchAsync(query, maxResults, true);
message = "...using normal Query search, Query " + query + ", max results " + maxResults.ToString();
}
}
catch (IQserException ex)
{
message = ex.Message;
}
}
if (results != null)
{
ICollection<LocalSearchResult> contentResults = new List<LocalSearchResult>();
foreach (SearchResult s in results)
{
var q = s.ToString();
var contentItem = await connector.GetConnected().GetContentAsync(s.ContentId);
LocalSearchResult lContent = new LocalSearchResult(contentItem);
lContent.Score = s.Score;
lContent.Relevance = s.Relevance;
lContent.MarkFullText(query);
contentResults.Add(lContent);
}
At the point where I call s.ToString() method, I get an error "Resource Map not found".
To explain where this comes from:
public static class AppResources
{
private static ResourceLoader resourceLoader;
static AppResources()
{
// Load local file Resources.resw by default
resourceLoader = new ResourceLoader();
}
public static string GetResources(string key)
{
if (string.IsNullOrEmpty(key))
throw new ArgumentNullException("key");
return resourceLoader.GetString(key);
}
}
and inside the overridden ToString() method there is code that looks as follows:
public override string ToString()
{
StringBuilder buf = new StringBuilder(AppResources.GetResources("InstrSearchResultContent"));
if (ContentId != -1)
{
buf.Append(AppResources.GetResources("StringContent") + " ID:" + ContentId.ToString() + " | ");
}
else
{
buf.Append(AppResources.GetResources("StringNo") + AppResources.GetResources("StringContent") + "ID" + " | ");
}
...
The resource file is called resources.resw and is the default resw file that ResourceLoader calls if no other is called.
Strangely enough, if I copy the resource file inside the client application locally, it is referenced correctly by all calls to the class library resource file and everything works.
This class library is supposed to be an SDK when finished. Do I need to distribute the resource file separately?
Such a problem I have never experienced with normal Class libraries and resx files. Resw is giving me the creeps..
It looks like you have to specify the name of the resource map when you create the ResourceLoader, like this:
resourceLoader = new ResourceLoader("Assembly/ResourceFile");
For example, if your class library was called "Company.Lib.dll", and your resource file was "Resources.resw", you would use:
resourceLoader = new ResourceLoader("Company.Lib/Resources");
This doesn't seem to be documented fully on MSDN - it suggests that you can just specify the name of your resource file, but it might be that that only works for resource files that are in the Windows Store application project. It was this page that showed me that, for libraries, you need to specify the assembly name as well.
I also had similar issue even with repeating all steps from How to load string resources.
The problem was that my Resources.resw file was empty. When I added some fake string to it all started working as expected.
I had a similar issue which i resolved by changing the Build Action of the resw file to PRIResource in the properties. I had renamed an existing resx to resw but the documentation doesn't mention that you also have to change the build action.
Accepted answer posted by #Rory MacLeod may no longer be true. I tried and VS warned that ResourceLoader(String) is deprecated. The following worked in my case:
var loader = ResourceLoader.GetForCurrentView();
string localName = loader.GetString("someKey");
I faced a similar issue when developing a UWP app with a class library.
So I have a /Strings/en-Us/Resource.resw file in my library.
ResourceLoader.GetForCurrentView().GetString("someKey");
gives an exception
new ResourceLoader("Company.Lib/Resources").GetString("someKey");
gives me a deprecation warning but works.
My solution which does not give a warning is this:
ResourceLoader.GetForViewIndependentUse("AssemblyNamespace/Resources").GetString("someKey");

Categories

Resources