# Modern approach to update an old package relying on PyCall and custom script to insall a python package

**URL:** <https://discourse.julialang.org/t/modern-approach-to-update-an-old-package-relying-on-pycall-and-custom-script-to-insall-a-python-package/137169>\
**Category:** General Usage\
**Tags:** pythoncall\
**Created:** [May 18, 2026, 2:49pm UTC](https://discourse.julialang.org/t/modern-approach-to-update-an-old-package-relying-on-pycall-and-custom-script-to-insall-a-python-package/137169 "2026-05-18T14:49:00Z")\
**Posts on this page:** 3\
**Page:** 1

<div class="post-metadata">

**Author:** ![sylvaticus](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/sylvaticus/32/203883_2.png) [@sylvaticus](https://discourse.julialang.org/u/sylvaticus)\
**Post date:** [May 18, 2026, 2:49pm UTC](https://discourse.julialang.org/t/modern-approach-to-update-an-old-package-relying-on-pycall-and-custom-script-to-insall-a-python-package/137169/1 "2026-05-18T14:49:00Z")

</div>

I am the maintainer of [OdsIO](https://github.com/sylvaticus/OdsIO.jl), an old package that wrap ezodf python module to read and write data on ODS (LibreOffice) spreadsheets.  
This has been my first package and at that time I used PyCall and made the installation of the python module on build.jl:

```julia-auto
using PyCall

println("Running build.jl for the OdsIO package.")

# Change that to whatever packages you need.
const PACKAGES = ["ezodf","lxml"]

# Use eventual proxy info
proxy_arg=String[]
if haskey(ENV, "http_proxy")
    push!(proxy_arg, "--proxy")
    push!(proxy_arg, ENV["http_proxy"])
end

# Import pip
try
    pyimport("pip")
catch
    # If it is not found, install it
    println("Pip not found on your sytstem. Downloading it.")
    get_pip = joinpath(dirname(@ __FILE__ ), "get-pip.py")
    download("https://bootstrap.pypa.io/get-pip.py", get_pip)
    run(`$(PyCall.python) $(proxy_arg) $get_pip --user`)
end

println("Installing required python packages using pip")
run(`$(PyCall.python) $(proxy_arg) -m pip install --user --upgrade pip setuptools`)
run(`$(PyCall.python) $(proxy_arg) -m pip install --user $(PACKAGES)`)

```

Now this approach has several limitations, and I am trying to “modernize it”.  
So, which is the standard way nowaday to create a Julia package that require a Python one?

I am trying (unsuccessfully) to use PythonCall/CondaPkg, by replacing the text above on build.jl with

```julia-auto
import CondaPkg
CondaPkg.add("ezodf")

```

and then using

```julia-auto
CondaPkg.add("ezodf")
const ezodf = pyimport("ezodf")
const pyio = pyimport("io")

```

in `src/OdsIO.jl`  
However I have various errors (from not knowing the ezods package or completelly crashing Julia.

So which is the approach in order to get a Julia package wrapping a Python module, without depending at all to what there is installed in the host system (i.e. whatever the host system has its own ezods module or not) ?

---

<div class="post-metadata">

**Author:** ![sylvaticus](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/sylvaticus/32/203883_2.png) [@sylvaticus](https://discourse.julialang.org/u/sylvaticus)\
**Post date:** [May 18, 2026, 5:48pm UTC](https://discourse.julialang.org/t/modern-approach-to-update-an-old-package-relying-on-pycall-and-custom-script-to-insall-a-python-package/137169/2 "2026-05-18T17:48:13Z")

</div>

I managed but my package is not running in VSCode.  
Actually, it has nothing to do with my package.

The following script runs in a julia terminal but not in VSCode, both with Julia 1.12.6:

```julia-auto
using Pkg
Pkg.activate(;temp=true)
Pkg.add(["CondaPkg","PythonCall"])
using PythonCall
import CondaPkg

CondaPkg.add("ezodf")
const ezodf_ref = Ref{Py}()
# This will go into the __init__ function in my package..
ezodf_ref[] = pyimport("ezodf")

ezodf = ezodf_ref[]
destDoc = ezodf.newdoc(doctype="ods", filename="foo.ods") # here it crashes Julia only in VSCode

```

Do you have an idea what the hell is happening ?

This is the output on the command line:

```julia-auto
$ julia
               _
   _ _ _(_)_ | Documentation: https://docs.julialang.org
  (_) | (_) (_) |
   _ _ _| |_ __ _ | Type "?" for help, "]?" for Pkg help.
  | | | | | | |/ _` | |
  | | |_| | | | (_| | | Version 1.12.6 (2026-04-09)
 _/ |\ __'_|_|_|\__'_| | Official https://julialang.org release
|__/ |

julia> using Pkg

julia> Pkg.activate(;temp=true);
  Activating new project at `/tmp/jl_x6kU8l`

julia> Pkg.add(["CondaPkg","PythonCall"]);
   Resolving package versions...
    Updating `/tmp/jl_x6kU8l/Project.toml`
  [992eb4ea] + CondaPkg v0.2.36
  [6099a3de] + PythonCall v0.9.34
    Updating `/tmp/jl_x6kU8l/Manifest.toml`
  [992eb4ea] + CondaPkg v0.2.36
  [9a962f9c] + DataAPI v1.16.0
  [e2d170a0] + DataValueInterfaces v1.0.0
  [82899510] + IteratorInterfaceExtensions v1.0.0
  [692b3bcd] + JLLWrappers v1.8.0
  [682c06a0] + JSON v1.6.0
  [1914dd2f] + MacroTools v0.5.16
  [0b3b1443] + MicroMamba v0.1.15
  [bac558e1] + OrderedCollections v1.8.1
  [69de0a69] + Parsers v2.8.4
  [fa939f87] + Pidfile v1.3.0
  [aea7be01] + PrecompileTools v1.3.4
  [21216c6a] + Preferences v1.5.2
  [6099a3de] + PythonCall v0.9.34
  [6c6a2e73] + Scratch v1.3.0
  [ec057cc2] + StructUtils v2.8.2
  [3783bdb8] + TableTraits v1.0.1
  [bd369af6] + Tables v1.12.1
  [e17b2a0c] + UnsafePointers v1.0.0
  [f8abcde7] + micromamba_jll v2.3.1+0
  [4d7b5844] + pixi_jll v0.41.3+0
  [0dad84c5] + ArgTools v1.1.2
  [56f22d72] + Artifacts v1.11.0
  [2a0f44e3] + Base64 v1.11.0
  [ade2ca70] + Dates v1.11.0
  [f43a241f] + Downloads v1.7.0
  [7b1f6079] + FileWatching v1.11.0
  [b77e0a4c] + InteractiveUtils v1.11.0
  [ac6e5ff7] + JuliaSyntaxHighlighting v1.12.0
  [4af54fe1] + LazyArtifacts v1.11.0
  [b27032c2] + LibCURL v0.6.4
  [76f85450] + LibGit2 v1.11.0
  [8f399da3] + Libdl v1.11.0
  [56ddb016] + Logging v1.11.0
  [d6f4376e] + Markdown v1.11.0
  [ca575930] + NetworkOptions v1.3.0
  [44cfe95a] + Pkg v1.12.1
  [de0858da] + Printf v1.11.0
  [9a3f8284] + Random v1.11.0
  [ea8e919c] + SHA v0.7.0
  [9e88b42a] + Serialization v1.11.0
  [f489334b] + StyledStrings v1.11.0
  [fa267f1f] + TOML v1.0.3
  [a4e569a6] + Tar v1.10.0
  [8dfed614] + Test v1.11.0
  [cf7118a7] + UUIDs v1.11.0
  [4ec0a83e] + Unicode v1.11.0
  [e66e0078] + CompilerSupportLibraries_jll v1.3.0+1
  [deac9b47] + LibCURL_jll v8.15.0+0
  [e37daf67] + LibGit2_jll v1.9.0+0
  [29816b5a] + LibSSH2_jll v1.11.3+1
  [14a3606d] + MozillaCACerts_jll v2025.11.4
  [458c3c95] + OpenSSL_jll v3.5.4+0
  [83775a58] + Zlib_jll v1.3.1+2
  [8e850ede] + nghttp2_jll v1.64.0+1
  [3f19e933] + p7zip_jll v17.7.0+0

julia> using PythonCall;
    CondaPkg Found dependencies: /home/lobianco/.julia/packages/PythonCall/JksWe/CondaPkg.toml
    CondaPkg Found dependencies: /home/lobianco/.julia/packages/CondaPkg/lKlVY/CondaPkg.toml
    CondaPkg Resolving changes
             + libstdcxx
             + libstdcxx-ng
             + openssl
             + python
    CondaPkg Initialising pixi
             │ /home/lobianco/.julia/artifacts/cefba4912c2b400756d043a2563ef77a0088866b/bin/pixi
             │ init
             │ --format pixi
             └ /tmp/jl_x6kU8l/.CondaPkg
✔ Created /tmp/jl_x6kU8l/.CondaPkg/pixi.toml
    CondaPkg Wrote /tmp/jl_x6kU8l/.CondaPkg/pixi.toml
             │ [dependencies]
             │ openssl = ">=3, <3.6"
             │ libstdcxx = ">=3.4,<=15.1"
             │ libstdcxx-ng = ">=3.4,<=15.1"
             │ 
             │ [dependencies.python]
             │ channel = "conda-forge"
             │ build = "*cp*"
             │ version = ">=3.10,!=3.14.0,!=3.14.1,<4"
             │ 
             │ [project]
             │ name = ".CondaPkg"
             │ platforms = ["linux-64"]
             │ channels = ["conda-forge"]
             │ channel-priority = "strict"
             └ description = "automatically generated by CondaPkg.jl"
    CondaPkg Installing packages
             │ /home/lobianco/.julia/artifacts/cefba4912c2b400756d043a2563ef77a0088866b/bin/pixi
             │ install
             └ --manifest-path /tmp/jl_x6kU8l/.CondaPkg/pixi.toml
✔ The default environment has been installed.

julia> import CondaPkg;

julia> CondaPkg.add("ezodf");
    CondaPkg Found dependencies: /tmp/jl_x6kU8l/CondaPkg.toml
    CondaPkg Found dependencies: /home/lobianco/.julia/packages/PythonCall/JksWe/CondaPkg.toml
    CondaPkg Found dependencies: /home/lobianco/.julia/packages/CondaPkg/lKlVY/CondaPkg.toml
    CondaPkg Resolving changes
             + ezodf
    CondaPkg Initialising pixi
             │ /home/lobianco/.julia/artifacts/cefba4912c2b400756d043a2563ef77a0088866b/bin/pixi
             │ init
             │ --format pixi
             └ /tmp/jl_x6kU8l/.CondaPkg
✔ Created /tmp/jl_x6kU8l/.CondaPkg/pixi.toml
    CondaPkg Wrote /tmp/jl_x6kU8l/.CondaPkg/pixi.toml
             │ [dependencies]
             │ openssl = ">=3, <3.6"
             │ libstdcxx = ">=3.4,<=15.1"
             │ libstdcxx-ng = ">=3.4,<=15.1"
             │ ezodf = "*"
             │ 
             │ [dependencies.python]
             │ channel = "conda-forge"
             │ build = "*cp*"
             │ version = ">=3.10,!=3.14.0,!=3.14.1,<4"
             │ 
             │ [project]
             │ name = ".CondaPkg"
             │ platforms = ["linux-64"]
             │ channels = ["conda-forge"]
             │ channel-priority = "strict"
             └ description = "automatically generated by CondaPkg.jl"
    CondaPkg Installing packages
             │ /home/lobianco/.julia/artifacts/cefba4912c2b400756d043a2563ef77a0088866b/bin/pixi
             │ install
             └ --manifest-path /tmp/jl_x6kU8l/.CondaPkg/pixi.toml
✔ The default environment has been installed.

julia> const ezodf_ref = Ref{Py}()
Base.RefValue{Py}(#undef)

julia> # This will go into the __init__ function in my package..
       ezodf_ref[] = pyimport("ezodf")
/tmp/jl_x6kU8l/.CondaPkg/.pixi/envs/default/lib/python3.14/site-packages/ezodf/tableutils.py:31: SyntaxWarning: "\d" is an invalid escape sequence. Such sequences will not work in the future. Did you mean "\\d"? A raw string is also an option.
  CELL_ADDRESS = re.compile('^([A-Z]+)(\d+)$')
Python: <module 'ezodf' from '/tmp/jl_x6kU8l/.CondaPkg/.pixi/envs/default/lib/python3.14/site-packages/ezodf/ __init__.py'>

julia> ezodf = ezodf_ref[]
Python: <module 'ezodf' from '/tmp/jl_x6kU8l/.CondaPkg/.pixi/envs/default/lib/python3.14/site-packages/ezodf/ __init__.py'>

julia> destDoc = ezodf.newdoc(doctype="ods", filename="foo.ods")
Python: <ezodf.document.PackagedDocument object at 0x780148993620>

julia> println("done!")
done!

```

And this is the screenshot I managed to get of the VSCode stack error:

 ![Screenshot From 2026-05-18 19-54-24](https://global.discourse-cdn.com/julialang/original/3X/8/d/8d8f9300258c2d4e017fb821b35397fe4a90000f.png)

---

<div class="post-metadata">

**Author:** ![sylvaticus](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/sylvaticus/32/203883_2.png) [@sylvaticus](https://discourse.julialang.org/u/sylvaticus)\
**Post date:** [May 18, 2026, 6:26pm UTC](https://discourse.julialang.org/t/modern-approach-to-update-an-old-package-relying-on-pycall-and-custom-script-to-insall-a-python-package/137169/3 "2026-05-18T18:26:03Z")

</div>

For some obscure reason I had to add this on CondaPkg.toml in the package root directory to limit Python version.

```julia-auto
    [deps.python]
    version = ">=3.10,<3.13"

```

Still unsure why this was giving an issue only in VSCode, but.. problem solved
