Linux中利用Pythonnet库实现Microsoft.CodeAnalysis的调用

简介

Microsoft.CodeAnalysis是一个开源的.NET编译器平台,可以作为一个NuGet软件包安装到项目中,也可以以dll的形式安装。本人想利用Microsoft.CodeAnalysis实现对c#语言在python环境下的解析,主要涉及到了利用Pythonnet库实现Microsoft.CodeAnalysis的调用


问题描述

在一个python项目里,需要用到c#源码的抽象语法树(AST),但是却遇到了不小的麻烦,陆陆续续解决了有好几天,涉及到的环节颇多,特此记录一下


配置步骤:

1、安装.NET SDK:.NET官方安装说明

建议直接使用官方的安装脚本dotnet-install.sh并运行,检查是否安装成功。

sudo chmod +x ./dotnet-install.sh
./dotnet-install.sh --version latest
dotnet --info 

2、 安装pythonnet

pip install pythonnet

这里有个坑,由于后续会 import clr 所以我在第一次安装的时候直接pip install clr 但其实这样是不正确的,利用clr.AddReference() 调用dll的时候会报错:AttributeError: module 'clr' has no attribute 'AddReference'。原因是直接pip安装的clr包同名但功能不同。

3、安装gcc

conda install -c conda-forge gcc

如果太慢可以换源

4、下载Microsoft.CodeAnalysis.dll

不熟悉dotnet工作机制的可能会在这一步困扰很久,当时我没有在dotnet的根目录下找到Microsoft.CodeAnalysis.dll,就想了以下一种比较容易的方式
1.利用dotnet新建一个最简单的项目

dotnet new console -o MyApp -f net6.0
cd sample1
dotnet run

2.在本项目中

dotnet add package Microsoft.CodeAnalysis.CSharp --version 4.5.0

3.进入项目文件夹

cd MyApp/bin/Debug/net6.0/

就可以看到Microsoft.CodeAnalysis.dll和Microsoft.CodeAnalysis.CSharp.dll啦,将其复制到你的python项目路径下,或者添加至sys.path中。

5、在python中利用clr调用dll

需要找一下自己的dotnet根路径和所调用的runtime配置文件路径,一般都如下所示

#待解析源码
source_code = """
using System;
namespace HelloWorld
{
    class Program
    {
        static void Main(string[] args)
        {
            Console.WriteLine("Hello, world!");
        }
    }
}
"""

from clr_loader import  get_coreclr
from pythonnet import set_runtime

rt =get_coreclr(dotnet_root='/usr/share/dotnet/',
				runtime_config="/usr/share/dotnet/shared/Microsoft.AspNetCore.App/6.0.14/Microsoft.AspNetCore.App.runtimeconfig.json")

clr.AddReference('Microsoft.CodeAnalysis') #这一步我曾经使用dll绝对路径的方式,可以通过编译,但是在后面的运行过程中还是无法获得Microsoft.CodeAnalysis的命名空间,关键在于将dll放至python路径
clr.AddReference("Microsoft.CodeAnalysis.CSharp")
from Microsoft.CodeAnalysis.CSharp import CSharpSyntaxTree
from Microsoft.CodeAnalysis import CSharp
tree = CSharpSyntaxTree.ParseText(source_code)

顺利实现。后续可以用实现树的遍历操作:

class_definition_nodes = [node for node in tree.GetRoot().DescendantNodes() if isinstance(node, CSharp.Syntax.ClassDeclarationSyntax)]
for class_node in class_definition_nodes:
    print(class_node.Identifier.ValueText)

可能c#还有其他的解析方法,比如用tree-sitter等库,欢迎有相似问题的找我讨论


  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 3
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

FlsrageZ

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值