import, uv, and module/package in Python

2 minute read

A really good video talks about morden Python project structures and tools like uv/poetry. Also explained what exactly import does

Video link module and package, uv, and package structure

1 module

Here is the example with mymath.py and main.py under same dir

print("exeucte mymath.py")
PI=3.14
def add(a,b)
  return a+b
def add_global(key, value)
  g = globals()
  g[key]=value

and here is the main function

import mymath
# import mymath as mm
# mm = mymath
mypath.add(1,2)
print(type(mypath)) # <class `module`>
  1. So the import is actually creating an instance from class module. It can be assigned to another variable mm, and that’s essencially what import mymath as mm does
  2. import a file multiple time, only the first time would execute the file
    import mymath as mm   # file execution
    import mymath as mm2  # no execution
    assert id(mm) == id(mm2)
    
  3. The module created by import is the global namespace
    print(dir(mm)) # [...,'PI','add']
    print(mm.foo) # error, no foo variable
    mm.add_global('foo', 'bar')
    print(mm.foo) # print bar
    
  4. Modify imported value won’t change the value in the original file
    from mymath import PI
    PI=999
    print(PI) #999
    print(mymath.PI) # 3.14
    from mymath import PI
    print("PI still is {PI}") # PI still is 3.14
    

2 package

  1. Assume there is folder called mymath with __init__.py in it The folder will have higher priority over a file and it’s imported as a package
    # - mymath
    #   - __init__.py (optional)
    #     print("executed __init__.py")
    # - mymath.py
    # - main.py
    import mymath # executed __init__.py
    import sys
    print(sys.path) # [., sys_path, ...]
    
  2. We can use PYTHONPATH env var to add sys.path
  3. When import mydir.subdir, it will firstly add mydir in current namespace, then add subdir to the namespace of mydir.
    #- mydir
    #  -subdir
    import mydir.subdir
    print(dir()) # [..., mydir]
    print(dir(mydir)) # [..., subdir]
    
  4. When from mydir import subdir, it will add both mydir and subdir in current namespace, then add subdir to the namespace of mydir same as above.
    from mydir import subdir
    import mydir
    print(dir()) #[..., mydir, subdir] NEW 
    print(dir(mydir)) # [..., subdir]  SAME as import mydir.subdir
    
  5. We can have relative import
    from . import aaa
    from .. import bbb
    

3 uv

  1. pip freeze > requirments.txt but current requirments.txt have issues of
    • List all the direct dependences and indirect dependences
    • pip uninstall ONLY remove the package but left orphan packages Alt text
  2. New python standard is using pyproject.toml with dependencies Alt text and multiple tools like mypy and pytest all have their config file built in
    [project]
    name='proj'
    version='0.1.0'
    [tool.mypy]
    exclude=['build/']
    [tool.pytest.init_options]
    testpaths=['tests']
    
  3. Following steps can be combined into one uv command, which is the high level wrapper for pip
    #python -m venv .venv
    #source .venv/bin/activate
    #vi pyproject.toml
    #pip install -e .
    uv add flask
    
  4. uv sync can read from pyproject.toml and create venv and finish all the installation
  5. uv run main.py can run the code inside the venv automatically

4 wheel and hatchling

  1. .whl file is essencially a zip package and be unzip to view contents
  2. METADATA file inside the package.version.dist-info contains the indirect dependencies
  3. Suggest to use the same folder name as the package name to avoid confusion Alt text
  4. There are multiple options can be used here and we choose the frontend uses build (Python default) and backend uses hatchling. The sample config is
    [build-system]
    requires=['hatchling']
    build-backend='hatchling.build'
    

    Alt text

Tags:

Categories:

Updated: