Estoy integrando IronPython (2.6.1) en un ensamblado C# y exponiendo varios objetos a scripts que se ejecutan con PythonEngine.ExecuteFile. Expongo ellos, ya sea conIncrustar IronPython, comando de ayuda integrado, mis objetos CLR
scope.SetVariable("SomeObject", new SomeObject())
o
engine.Execute("from MyNamespace import SomeObject", scope)
dependiendo de cómo los guiones los utilizan. Mi conjunto de aplicación se añade al motor con
engine.Runtime.LoadAssembly(Assembly.GetExecutingAssembly())
Ahora un script puede ejecutar help(SomeObject)
y volcar la pequeña información de ayuda (*), sin embargo es incompleta. Ninguno de los eventos o propiedades del objeto (público, por supuesto) aparece y muchos de los miembros 'incorporados' también faltan.
Aquí está la parte extraña; Si enciendo ipy.exe y ejecuto lo siguiente:
import sys
sys.path.append('<location of my app>')
import clr
clr.AddReferenceToFile('myapp.exe')
from MyNamespace import SomeObject
help(SomeObject)
¡Obtengo un volcado diferente, completo con todos los miembros que faltan!
¿Por qué las dos difieren?
Bono pregunta: Suponiendo que conseguir que funcione correctamente, es posible añadir un texto descriptivo en mis objetos CLR a la salida de la ayuda()? ¿Te gusta desde el script, en tus tipos nativos de python? Mi primera suposición fue la DescripciónAtributo, pero eso no funcionó.
(*) Obviamente, un script final y funcional no lo haría, pero es extremadamente útil al escribir/probar el script.
Respondido
Aquí es un programa de consola completa que ilustra la forma de importar el sitio que sustituye a la ayuda interna usless() con el estándar ayuda biblioteca de Python().
using System;
using System.Collections.Generic;
using System.Reflection;
using IronPython.Hosting;
using IronPython.Runtime;
using Microsoft.Scripting.Hosting.Providers;
namespace MyApp
{
class Program
{
static void Main(string[] args)
{
// Work around issue w/ pydoc - piping to more doesn't work so instead indicate that we're a dumb terminal
if (Environment.GetEnvironmentVariable("TERM") == null)
Environment.SetEnvironmentVariable("TERM", "dumb");
var engine = Python.CreateEngine();
// Add standard Python library path (is there a better way to do this??)
PythonContext context = HostingHelpers.GetLanguageContext(engine) as PythonContext;
ICollection<string> paths = context.GetSearchPaths();
paths.Add(@"C:\Program Files (x86)\IronPython 2.6\Lib");
context.SetSearchPaths(paths);
// Import site module
engine.ImportModule("site");
engine.Runtime.LoadAssembly(Assembly.GetEntryAssembly());
var scope = engine.CreateScope();
scope.SetVariable("SomeObject", new SomeObject());
engine.Execute("help(SomeObject)", scope);
}
}
/// <summary>
/// Description of SomeObject.
/// </summary>
public class SomeObject
{
/// <summary>
/// Description of SomeProperty.
/// </summary>
public int SomeProperty { get; set; }
/// <summary>
/// Description of SomeMethod.
/// </summary>
public void SomeMethod() { }
/// <summary>
/// Description of SomeEvent.
/// </summary>
public event EventHandler SomeEvent;
}
}
Pude verificar que esta respuesta es correcta, sin embargo, no puedo (hasta ahora) descubrir cómo importar site.py programáticamente. Mi verificación consistió en construir ipy.exe (es todo un archivo .cs simple) y probar el procedimiento de ipy anterior. Obtengo los resultados de ayuda rotos. Si luego hago que la biblioteca estándar de Python esté disponible para este nuevo ipy.exe, obtengo los resultados de ayuda correctos. Así que la solución para cargar la biblioteca estándar está enterrada profundamente en los tazones de Microsoft.Scripting.Hosting o IronPython.Hosting. OO-Spaghetti sería una palabra amable para ese desastre. – Tergiver
Descubrí cómo cargar el módulo del sitio y actualicé mi pregunta anterior. – Tergiver