Dezvoltarea pachetului Python pentru dezvoltatorii R

URMĂREȘTE-NE
16,065FaniÎmi place
1,142CititoriConectați-vă

Am învățat multe dezvoltând și contribuind la diverse pachete R de -a lungul anilor. Fără a avea (încă!) Un pachet personal pe CRAN, folosesc zilnic dezvoltarea pachetelor și am avut șansa de a antrena mai mulți colegi sau studenți în această practică. Odată ce teama primului pachet este depășită, dezvoltarea pachetelor în R devine fluidă, în special datorită unui ecosistem bine integrat de instrumente: devtools, usethis, testthat, roxygen2etc. Și dacă utilizați RStudio, numeroasele utilități accesibile cu câteva clicuri simplifică viața și mai mult.

Dorind să -mi îmbunătățesc abilitățile Python, am vrut să văd dacă acest cadru liniștitor a existat și în Python prin crearea unui proiect mic de pachete – o modalitate de a învăța prin comparație directă.

Experiența mea Python este mult mai limitată decât experiența mea, dar sper că acest feedback vă va fi util. Nu ezitați să subliniați erori sau inexactități! 😀

Lectură fericită 🐍


Alegerea instrumentului de dezvoltare

În ultimele luni, am văzut multe mesaje care laudă uv instrument ca manager de mediu și dependență Python. Dacă înțeleg corect, uv înlocuiește ambele pip, venvși într -o oarecare măsură poetry. De asemenea, oferă mai multe comenzi rapide utile pentru dezvoltarea pachetelor.

poetry Ar fi putut fi o altă opțiune, dar încă nu am avut ocazia să o încerc.


Crearea de pachete

În R, folosesc deseori usethis::create_package() pentru a crea un pachet nou.

Cu uvputeți face același lucru cu următoarea comandă:

uv init blueskypy --lib

Aceasta creează o structură de proiect similară cu cea a unui pachet R:

blueskypy/
├── pyproject.toml
├── README.md
├── .gitignore
├── .python-version
└── src/
    └── blueskypy/
        ├── __init__.py
        └── py.typed

Dezvoltatorii R vor recunoaște mai multe elemente familiare:

  • README.md: Descrierea pachetului, instalare, exemple de utilizare.
  • .gitignore: fișiere pentru a exclude din versiune.
  • src/: director de fișiere sursă (echivalent cu R/ folder într -un pachet R).
  • pyproject.toml: metadate, dependențe etc. (echivalent cu cele DESCRIPTION fişier).

Alte fișiere sunt specifice Python, py.typed şi python-version.


Configurarea controlului versiunii

În R, rareori folosesc usethis::use_git()preferând linia de comandă.
Aceeași abordare aici:

git init
git remote add origin repo_url.git
git branch -M main

Adăugarea unei funcții și dependențele sale

Pentru a interacționa cu API -ul bluesky, am ales să folosesc requests bibliotecă.

În R, aș fi folosit usethis::use_package().
În python cu uvtrebuie doar să alergi:

uv add requests

Această comandă actualizează pyproject.toml fișier și creează un uv.lock fișier, care detaliază toate dependențele exacte ale proiectului:

dependencies = (
    "requests>=2.32.5",
)

Apoi adaug prima mea funcție în src/blueskypy/session.py (Nu am putut găsi un echivalent cu usethis::use_r() în Python):

"""Bluesky session management module"""
import requests

def create_session(
    handle=None,
    password=None,
    url="https://bsky.social/xrpc/com.atproto.server.createSession",
):
    """Create a Bluesky session and return the access JWT.

    Args:
        handle: The Bluesky handle (if None, uses BLUESKY_HANDLE env var).
        password: The password (if None, uses BLUESKY_PASSWORD env var).
        url: The Bluesky API URL.

    Returns:
        The access JWT.
    """
    # ... code ...
    return "access_jwt"

Documentația este aici integrată sub forma unui Docstringun concept apropiat de roxygen2 Documentare în R (#' @parametc.).

În IDE -ul cursorului, folosesc extensia Pylance, care verifică prezența documentelor și „se plânge” în cazul documentației lipsă – o caracteristică pe care mi -ar plăcea să o văd în R! Și cursorul îmi permite să le completez foarte repede.


Testarea și reîncărcarea codului

În R, folosesc load_all() Aproape compulsiv pentru a -mi reîncărca pachetul după fiecare modificare.
În Python, echivalentul este instalarea „editabilă”:

uv pip install -e .

Acest lucru face ca pachetul să fie disponibil fără a fi nevoie să -l reinstalați cu fiecare schimbare.

Pentru a rula un script de testare:

uv run script.py

Și dacă lucrați într -un caiet de cvarto, puteți forța reîncărcarea unui modul modificat fără a reporni kernelul datorită:

import blueskypy.bluesky_session
import importlib
importlib.reload(blueskypy.bluesky_session)
blueskypy.bluesky_session.create_session()  

Acest lucru îmi permite să iau în considerare modificările codului în create_session() Funcționați fără a fi nevoie să reporniți nucleul.

Acesta este echivalentul python al devtools::load_all() În R. Dar mi se pare mult mai greu decât în ​​R 🫤.


Documentare și viniete

În același mod în care utilizarea etichetelor Roxygen2 ne permite să obținem o pagină de documentare, documentele pe care le -am folosit pentru a ne documenta create_session() Funcția ne permite să generăm o pagină de documentare pentru această funcție.

Nativ, documentația se afișează în terminal și se pare că nu este posibilă afișarea pur și simplu a documentației în format HTML, ca într -un pachet R.

În funcție de IDE utilizat, pagina de documentare poate fi afișată și interactiv, trecând peste numele funcției.


Adăugând o vinie

Vignetele sunt pagini de documentare mai cuprinzătoare decât paginile de documentare funcționale. În R, puteți crea cu ușurință o vinie cu usethis::use_vignette() funcţie.

În Python, am impresia că trebuie să săpați în sphinx Instrument, care oferă viniete de scriere pe baza formatului Markdown (deci un utilizator a priori r nu ar fi prea pierdut!).


Datele interne ale pachetului

În proiectele mele R, sunt obișnuit să folosesc data-raw/ folder pentru a introduce date și data/ Folder pentru date care sunt incluse în pachet. Acest lucru este util în special pentru furnizarea de exemple ușor reproductibile pentru utilizatorii de pachete, fie în readme, paginile de ajutor pentru funcții sau viniete.

În Python, nu am găsit un echivalent cu aceste foldere, dar am putut încă să introduc date în pachet prin crearea unei funcții care returnează datele manipulabile de către utilizator.

Aceste date conține un eșantion de postări bluesky. Am stocat un fișier JSON într -un data/ Folder prezent la același nivel cu codul sursă (am impresia că Python este mai permis decât R pentru stocarea fișierelor/folderelor din pachet).

Și până la urmă am un load_sample_posts() Funcție care îmi permite să încărc aceste date în mediul de lucru.

"""Data loading utilities for the blueskypy package."""

import json
from importlib.resources import files

def load_sample_posts():
    """Load sample posts from the data directory."""
    data_file = files("blueskypy") / "data" / "sample_posts.json"
    with open(data_file, "r", encoding="utf-8") as f:
        json_content = json.load(f)
    return json_content

Cod de depanare

Debuggarea nu este specifică dezvoltării pachetelor, dar este un pas esențial în orice abordare de dezvoltare.

În R, foarte des folosesc browser() sau debugonce() – Două funcții indispensabile pentru înțelegerea comportamentului codului, în special în funcțiile cuibărite.

În Python, cel mai direct echivalent este încorporat breakpoint() Funcție, pe care o așezați acolo unde doriți să suspendați execuția. Când a ajuns, interpretul deschide o sesiune interactivă (gestionată de modulul PDB), care vă permite să inspectați variabile, să executați instrucțiuni pas cu pas și să reluați execuția.


Teste și verificări

Testele unitare sunt plasate într -un tests/ Folder, pe care l -am creat manual.
Eu folosesc pytest Pentru a le rula:

pytest tests/

Acesta este echivalentul devtools::test() În R.

Pentru a verifica calitatea codului și a documentației într -un mod mai global, nu am găsit un instrument echivalent cu devtools::check() În R. Uneori, acest instrument este cel mai rău coșmar al meu … dar de cele mai multe ori este un salvator!


Instalarea pachetului

Instalarea locală se face prin:

uv pip install .

Concluzie

În calitate de dezvoltator R, nu m -am pierdut complet când am dezvoltat un pachet Python.
Logica structurii și a organizării rămâne destul de similară, chiar dacă practica diferă.

Câteva puncte mi s -au părut mai puțin fluide:

  • Documentație: în R, roxygen2viniete și pkgdown Formați un ecosistem formidabil eficient.
  • load_all(): Python necesită un pic mai multă gimnastică între reload() și medii „editabile”.
  • devtools::check(): Nu am găsit un instrument la fel de complet și integrat.

Dar, în general, această experiență mi -a permis să înțeleg mai bine lumea Python și să realizez cât de mult R a reușit să facă dezvoltarea pachetelor simplă, integrată și coerentă.

Sursele de pachete sunt disponibile aici. (Cu ceva mai multe funcții decât prezentate în articol)

Din nou, nu ezitați să subliniez erori pe care le -am făcut sau să mă ghidez despre lucrurile cu care am avut mai multe dificultăți!

Mulțumesc tuturor!

Dominic Botezariu
Dominic Botezariuhttps://www.noobz.ro/
Creator de site și redactor-șef.

Cele mai noi știri

Pe același subiect

LĂSAȚI UN MESAJ

Vă rugăm să introduceți comentariul dvs.!
Introduceți aici numele dvs.