I am using pythonnet to call .NET dlls from Python. My code all works on my local machine, but it's failing when I unit test on the BitBucket server.
First, I have a step that builds a dummy .NET 6 exe in order to trigger download of the nuget packages. That's running image: mcr.microsoft.com/dotnet/sdk:6.0
and creates an artifact to use in the next step.
Then I set up the pythonnet environment on image image: python:3.11
:
- if [ -f unit_test_requirements.txt ]; then pip install -r unit_test_requirements.txt; fi
- export PYTHONPATH=$PYTHONPATH:$BITBUCKET_CLONE_DIR/ctop:$ARCHIVE
# Pure python tests that run fine here...
- wget https://dot.net/v1/dotnet-install.sh -O dotnet-install.sh
- chmod +x ./dotnet-install.sh
- ./dotnet-install.sh --runtime dotnet --version latest
- export DOTNET_ROOT=$HOME/.dotnet
- export PATH=$PATH:$DOTNET_ROOT:$DOTNET_ROOT/tools
- export PYTHONPATH=$PYTHONPATH:$DOTNET_ROOT:$DOTNET_ROOT/tools
pythonnet 3.0.1 installs
Collecting pythonnet (from -r unit_test_requirements.txt (line 3))
Using cached pythonnet-3.0.1-py3-none-any.whl (284 kB)
python -c "import sys; print(sys.path)"
prints the expected folders.
The errors I was getting in unit testing were buried deep in the import tree, so I simplified. I can load my own Dll that has a dependency on System.Text.Json 2 levels deep. I can load classes from System namespace. System.Text.Json exists in my archived folder, but when I try to load System.Text.Json, I get an error. The System.Text.Json in my solution is 7.0.3, the version of the file in the folder says 7.0.723.27404, but ILSpy reports the version (7.0.0.0) and token matching the error message.
+ python -c "from pathlib import Path;print(Path('.../My.A.dll').exists())"
True
+ python -c "from pythonnet import load;load('coreclr');import clr;clr.AddReference('My.A');from My.A.Namespace import B"
+ python -c "from pythonnet import load;load('coreclr');import clr;from System import Guid, String, Action"
+ python -c "from pathlib import Path;print(Path('.../System.Text.Json.dll').exists())"
True
+ python -c "from pythonnet import load;load('coreclr');import clr;clr.AddReference('System.Text.Json');import clr;from System.Text.Json import JsonConverter"
Traceback (most recent call last):
File "<string>", line 1, in <module>
System.IO.FileLoadException: Could not load file or assembly 'System.Text.Json, Version=7.0.0.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51'.
I downloaded the artifact to my local PC, changed my local pythonpath to point there, and all these commands pass fine on my local PC, with fairly robust unit testing working on local. So it's not the artifact itself. (Yes, in a fresh console window started after I changed the env variables.)
I don't think it's a .NET version problem. I'm using pythonnet 3.0.1, so it's not a problem with PythonNet 2.x not supporting core. System.Json.Text 7.0.3 supports .NET 6, .NET Standard 2.0, and .NET Framework 4.6.2, so it should load in any case. I am doing all the steps to load core. I'm getting .NET 6 installed in my steps:
+ ./dotnet-install.sh --runtime dotnet --version latest
...
dotnet-install: Installed version is 6.0.21
...
dotnet-install: Installation finished successfully.
I have a second Windows environment also getting similar errors, but I don't have direct access to it, so I'm tackling the CI/Bitbucket environment first, hoping it's a common root issue.