Python 作为 C# 的 post 构建步骤

Python as a post-build step to C#

我正在研究将 python 作为 C# 构建的一部分执行的方法。

具体来说,我想通过 python.net 创建一个基于 C# 项目的 Python 包。我的总体想法是先构建 C# 项目。然后,作为某种 post-构建步骤,调用 python 以基于新生成的 NET 程序集构建包。

我不能假设 python 会安装在构建主机上,所以理想情况下我想包括一个“便携式” - 更理想的是,基于 nuget - python 发行版。

我找到了一个很有前途的 nuget package,但我不完全确定它的用途。它不包含 C# 代码,但包含所有 python 个二进制文件,并具有如下 copy/pasted 的构建道具以供参考。

鉴于该包的道具 - 我可以以某种方式从我自己的项目中引用它的二进制文件作为 post-构建步骤吗?

比如说,我想在我自己的项目中添加一个 post-build 步骤,它只是在构建之后调用“python.exe”。我该怎么做?

我自己的项目:

<Project Sdk="Microsoft.NET.Sdk">

  <PropertyGroup>
    <OutputType>Exe</OutputType>
    <TargetFramework>netcoreapp2.1</TargetFramework>
    <GenerateProgramFile>false</GenerateProgramFile>
  </PropertyGroup>

  <ItemGroup>
    <PackageReference Include="python" Version="3.10.0-a6" />
  </ItemGroup>
  
  <Target Name="MyCustomStep" AfterTargets="Build">
    <!-- .. now what? I can't seem to access. e.g. @(PythonHome) or $(PythonHome) from here --/>
  <Target>

</Project>

来自 nuget 的 python 包的属性:

<?xml version="1.0" encoding="utf-8"?>
<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
  <PropertyGroup Condition="$(Platform) == 'X64'">
    <PythonHome Condition="$(PythonHome) == ''">$([System.IO.Path]::GetFullPath("$(MSBuildThisFileDirectory)\..\..\tools"))</PythonHome>
    <PythonInclude>$(PythonHome)\include</PythonInclude>
    <PythonLibs>$(PythonHome)\libs</PythonLibs>
    <PythonTag>3.10</PythonTag>
    <PythonVersion>3.10.0-a6</PythonVersion>

    <IncludePythonExe Condition="$(IncludePythonExe) == ''">true</IncludePythonExe>
    <IncludeDistutils Condition="$(IncludeDistutils) == ''">false</IncludeDistutils>
    <IncludeLib2To3 Condition="$(IncludeLib2To3) == ''">false</IncludeLib2To3>
    <IncludeVEnv Condition="$(IncludeVEnv) == ''">false</IncludeVEnv>

    <GetPythonRuntimeFilesDependsOn>_GetPythonRuntimeFilesDependsOn310_None;$(GetPythonRuntimeFilesDependsOn)</GetPythonRuntimeFilesDependsOn>
  </PropertyGroup>

  <ItemDefinitionGroup Condition="$(Platform) == 'X64'">
    <ClCompile>
      <AdditionalIncludeDirectories>$(PythonInclude);%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
      <RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>
    </ClCompile>
    <Link>
      <AdditionalLibraryDirectories>$(PythonLibs);%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
    </Link>
  </ItemDefinitionGroup>

  <Target Name="GetPythonRuntimeFiles" Returns="@(PythonRuntime)" DependsOnTargets="$(GetPythonRuntimeFilesDependsOn)" />

  <Target Name="_GetPythonRuntimeFilesDependsOn310_None" Returns="@(PythonRuntime)">
    <ItemGroup>
      <_PythonRuntimeExe Include="$(PythonHome)\python*.dll" />
      <_PythonRuntimeExe Include="$(PythonHome)\python*.exe" Condition="$(IncludePythonExe) == 'true'" />
      <_PythonRuntimeExe>
        <Link>%(Filename)%(Extension)</Link>
      </_PythonRuntimeExe>
      <_PythonRuntimeDlls Include="$(PythonHome)\DLLs\*.pyd" />
      <_PythonRuntimeDlls Include="$(PythonHome)\DLLs\*.dll" />
      <_PythonRuntimeDlls>
        <Link>DLLs\%(Filename)%(Extension)</Link>
      </_PythonRuntimeDlls>
      <_PythonRuntimeLib Include="$(PythonHome)\Lib\**\*" Exclude="$(PythonHome)\Lib\**\*.pyc;$(PythonHome)\Lib\site-packages\**\*" />
      <_PythonRuntimeLib Remove="$(PythonHome)\Lib\distutils\**\*" Condition="$(IncludeDistutils) != 'true'" />
      <_PythonRuntimeLib Remove="$(PythonHome)\Lib\lib2to3\**\*" Condition="$(IncludeLib2To3) != 'true'" />
      <_PythonRuntimeLib Remove="$(PythonHome)\Lib\ensurepip\**\*" Condition="$(IncludeVEnv) != 'true'" />
      <_PythonRuntimeLib Remove="$(PythonHome)\Lib\venv\**\*" Condition="$(IncludeVEnv) != 'true'" />
      <_PythonRuntimeLib>
        <Link>Lib\%(RecursiveDir)%(Filename)%(Extension)</Link>
      </_PythonRuntimeLib>
      <PythonRuntime Include="@(_PythonRuntimeExe);@(_PythonRuntimeDlls);@(_PythonRuntimeLib)" />
    </ItemGroup>

    <Message Importance="low" Text="Collected Python runtime from $(PythonHome):%0D%0A@(PythonRuntime->'  %(Link)','%0D%0A')" />
  </Target>
</Project>

那是为了使用内部 nuget 而不是你的主项目。您无法在主项目下获得 属性。

你必须使用我的功能:

1) 编辑 csproj 文件并将其设置为您的 PackageReference python

 <GeneratePathProperty>true</GeneratePathProperty>

像这样:

 <ItemGroup>
    <PackageReference Include="python" Version="3.10.0-a6">
      <GeneratePathProperty>true</GeneratePathProperty>
    </PackageReference>
  </ItemGroup>

2) 然后,你可以使用$(Pkgpython)获取那个路径。

<Target Name="MyCustomStep" AfterTargets="Build">
    <Exec Command="$(Pkgpython)\tools\python.exe" />
</Target>