【问题标题】:Embedding IronPython, built-in help command, my CLR objects嵌入 IronPython、内置帮助命令、我的 CLR 对象
【发布时间】:2011-01-08 19:16:06
【问题描述】:

我将 IronPython (2.6.1) 嵌入到 C# 程序集中,并将多个对象公开给使用 PythonEngine.ExecuteFile 执行的脚本。我将它们暴露在

scope.SetVariable("SomeObject", new SomeObject())

engine.Execute("from MyNamespace import SomeObject", scope)

取决于脚本如何使用它们。我的应用程序程序集被添加到引擎中

engine.Runtime.LoadAssembly(Assembly.GetExecutingAssembly())

现在脚本可以执行help(SomeObject) 并转储漂亮的小帮助信息(*),但是它不完整。对象的任何事件或属性(当然是公共的)都没有显示,并且许多“内置”成员也丢失了。

这是奇怪的部分;如果我启动 ipy.exe 并执行以下命令:

import sys
sys.path.append('<location of my app>')
import clr
clr.AddReferenceToFile('myapp.exe')
from MyNamespace import SomeObject
help(SomeObject)

我得到一个不同的转储,包含所有失踪的成员!

为什么两者不同?

额外问题:假设我让它正常工作,是否可以将我的 CLR 对象上的描述性文本添加到 help() 的输出中?就像你可以在脚本中,在你的 python-native 类型上一样?我的第一个猜测是 DescriptionAttribute,但它不起作用。

(*) 显然,最终的工作脚本不会这样做,但它在编写/测试脚本时非常有用。

已回答

这是一个完整的控制台程序,它说明了如何导入站点,该站点将无用的内部 help() 替换为标准 python 库 help()。

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;
    }
}

【问题讨论】:

    标签: c# ironpython embedding


    【解决方案1】:

    我的猜测是,在您的应用中,您没有导入标准库。 IronPython 包含一个内置的帮助函数,标准库包含一个由 site.py 安装的帮助函数。如果您确保在托管时标准库可用,然后在创建引擎时导入 site.py,那么您应该获得标准库帮助。话虽如此,内置帮助没有记录事件和属性可能是一个错误或缺失的功能。

    关于文档 - 是的,您只需要使用 C# 的 doc cmets 并使用 /doc:MyAssemblyName.xml 选项进行构建。如果 XML 文件与程序集位于同一目录中,IronPython 将读取文档字符串并为 doc 属性提供它们,然后 help() 读取。

    【讨论】:

    • 我能够验证这个答案是否正确,但是我(到目前为止)无法弄清楚如何以编程方式导入 site.py。我的验证包括构建 ipy.exe(它只是一个简单的 .cs 文件)并尝试上面的 ipy 程序。我得到了损坏的帮助结果。如果我随后将标准 python 库提供给这个新的 ipy.exe,我会得到正确的帮助结果。因此,加载标准库的解决方案深埋在 Microsoft.Scripting.Hosting 或 IronPython.Hosting 中。 OO-Spaghetti 会是这个烂摊子的好词。
    • 我想出了如何加载站点模块并更新我上面的问题。
    猜你喜欢
    • 2020-09-19
    • 1970-01-01
    • 2021-01-13
    • 2021-08-20
    • 1970-01-01
    • 1970-01-01
    • 2020-08-12
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多