Python as a post-build step to C#

  Uncategorised

I’m looking into ways to execute python as part of a C# build.

Specifically, I want to create a Python package based on a C# project through python.net. My general idea was to build the C# project first. And then, as some sort of post-build step, invoke python to build a package based on the newly generated NET assemblies.

I can’t presume python will installed on the build host, so ideally I want to include a "portable" – even more ideally, nuget-based – python distribution.

I have found a promising nuget package, but am not entirely sure of its usage. It incldues no C# code, but has all python binaries included, and has build props as copy/pasted below for reference.

Given on that package’s props – can I somehow reference its binaries from my own project as a post-build step?

Say, for example, I want to add a post-build step to my own project, that simply just invokes "python.exe" after the build. How could I do that?

My own project:

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

Props of the python package from nuget:

<?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)Libsite-packages***" />
      <_PythonRuntimeLib Remove="$(PythonHome)Libdistutils***" Condition="$(IncludeDistutils) != 'true'" />
      <_PythonRuntimeLib Remove="$(PythonHome)Liblib2to3***" Condition="$(IncludeLib2To3) != 'true'" />
      <_PythonRuntimeLib Remove="$(PythonHome)Libensurepip***" Condition="$(IncludeVEnv) != 'true'" />
      <_PythonRuntimeLib Remove="$(PythonHome)Libvenv***" 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%[email protected](PythonRuntime->'  %(Link)','%0D%0A')" />
  </Target>
</Project>

Source: Visual Studio Questions

LEAVE A COMMENT