{"id":49656840,"url":"https://github.com/saleepeppe/logpose","last_synced_at":"2026-05-06T10:31:30.685Z","repository":{"id":62576766,"uuid":"126728625","full_name":"saleepeppe/logpose","owner":"saleepeppe","description":"Log library for python (suitable for ML prototyping and jupyter projects in general)","archived":false,"fork":false,"pushed_at":"2018-06-28T21:28:02.000Z","size":35,"stargazers_count":2,"open_issues_count":4,"forks_count":0,"subscribers_count":2,"default_branch":"master","last_synced_at":"2024-11-29T15:51:49.416Z","etag":null,"topics":["data-science","jupyter-notebook","logging","machine-learning","python"],"latest_commit_sha":null,"homepage":null,"language":"Python","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/saleepeppe.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2018-03-25T18:42:45.000Z","updated_at":"2019-04-29T14:01:53.000Z","dependencies_parsed_at":"2022-11-03T17:36:50.815Z","dependency_job_id":null,"html_url":"https://github.com/saleepeppe/logpose","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/saleepeppe/logpose","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/saleepeppe%2Flogpose","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/saleepeppe%2Flogpose/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/saleepeppe%2Flogpose/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/saleepeppe%2Flogpose/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/saleepeppe","download_url":"https://codeload.github.com/saleepeppe/logpose/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/saleepeppe%2Flogpose/sbom","scorecard":{"id":796285,"data":{"date":"2025-08-11","repo":{"name":"github.com/saleepeppe/logpose","commit":"41dd6edbc107df6d461e7fbc79b8173c73a1b2f2"},"scorecard":{"version":"v5.2.1-40-gf6ed084d","commit":"f6ed084d17c9236477efd66e5b258b9d4cc7b389"},"score":3,"checks":[{"name":"Token-Permissions","score":-1,"reason":"No tokens found","details":null,"documentation":{"short":"Determines if the project's workflows follow the principle of least privilege.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#token-permissions"}},{"name":"Code-Review","score":0,"reason":"Found 0/30 approved changesets -- score normalized to 0","details":null,"documentation":{"short":"Determines if the project requires human code review before pull requests (aka merge requests) are merged.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#code-review"}},{"name":"Packaging","score":-1,"reason":"packaging workflow not detected","details":["Warn: no GitHub/GitLab publishing workflow detected."],"documentation":{"short":"Determines if the project is published as a package that others can easily download, install, easily update, and uninstall.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#packaging"}},{"name":"SAST","score":0,"reason":"no SAST tool detected","details":["Warn: no pull requests merged into dev branch"],"documentation":{"short":"Determines if the project uses static code analysis.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#sast"}},{"name":"Pinned-Dependencies","score":-1,"reason":"no dependencies found","details":null,"documentation":{"short":"Determines if the project has declared and pinned the dependencies of its build process.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#pinned-dependencies"}},{"name":"Binary-Artifacts","score":10,"reason":"no binaries found in the repo","details":null,"documentation":{"short":"Determines if the project has generated executable (binary) artifacts in the source repository.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#binary-artifacts"}},{"name":"Maintained","score":0,"reason":"0 commit(s) and 0 issue activity found in the last 90 days -- score normalized to 0","details":null,"documentation":{"short":"Determines if the project is \"actively maintained\".","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#maintained"}},{"name":"Dangerous-Workflow","score":-1,"reason":"no workflows found","details":null,"documentation":{"short":"Determines if the project's GitHub Action workflows avoid dangerous patterns.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#dangerous-workflow"}},{"name":"CII-Best-Practices","score":0,"reason":"no effort to earn an OpenSSF best practices badge detected","details":null,"documentation":{"short":"Determines if the project has an OpenSSF (formerly CII) Best Practices Badge.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#cii-best-practices"}},{"name":"Security-Policy","score":0,"reason":"security policy file not detected","details":["Warn: no security policy file detected","Warn: no security file to analyze","Warn: no security file to analyze","Warn: no security file to analyze"],"documentation":{"short":"Determines if the project has published a security policy.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#security-policy"}},{"name":"Vulnerabilities","score":10,"reason":"0 existing vulnerabilities detected","details":null,"documentation":{"short":"Determines if the project has open, known unfixed vulnerabilities.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#vulnerabilities"}},{"name":"License","score":10,"reason":"license file detected","details":["Info: project has a license file: LICENSE:0","Info: FSF or OSI recognized license: Apache License 2.0: LICENSE:0"],"documentation":{"short":"Determines if the project has defined a license.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#license"}},{"name":"Fuzzing","score":0,"reason":"project is not fuzzed","details":["Warn: no fuzzer integrations found"],"documentation":{"short":"Determines if the project uses fuzzing.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#fuzzing"}},{"name":"Signed-Releases","score":-1,"reason":"no releases found","details":null,"documentation":{"short":"Determines if the project cryptographically signs release artifacts.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#signed-releases"}},{"name":"Branch-Protection","score":0,"reason":"branch protection not enabled on development/release branches","details":["Warn: branch protection not enabled for branch 'master'"],"documentation":{"short":"Determines if the default and release branches are protected with GitHub's branch protection settings.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#branch-protection"}}]},"last_synced_at":"2025-08-23T09:06:05.711Z","repository_id":62576766,"created_at":"2025-08-23T09:06:05.711Z","updated_at":"2025-08-23T09:06:05.711Z"},"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":32689066,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-06T08:33:17.875Z","status":"ssl_error","status_checked_at":"2026-05-06T08:33:17.221Z","response_time":117,"last_error":"SSL_connect returned=1 errno=0 peeraddr=140.82.121.6:443 state=error: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["data-science","jupyter-notebook","logging","machine-learning","python"],"created_at":"2026-05-06T10:31:29.981Z","updated_at":"2026-05-06T10:31:30.675Z","avatar_url":"https://github.com/saleepeppe.png","language":"Python","funding_links":[],"categories":[],"sub_categories":[],"readme":"# logpose\nLog library for Data Science written in Python (suitable for ML prototyping and jupyter projects in general).\n\n- Do you prototype in jupyter before deploy your code?\n- Do you run several python simulations and after a while you forget to keep track of your trials?\n- Are you looking for a python library to store all the hyper-parameters tested tuning a ML algorithm?\n\n**Logpose** is here for you! Logpose generates YAML files to track each simulation run. \nAt the moment the library is under development. Use it but be aware that the API might change.\n\nI daily use this library for work, so it might not have reached a stable point but it is usable.\nAny suggestion, feature request or support is more than welcome.\n\n# Install\nLogpose is also installable via pip:\n```\npip install logpose\n```\nIt might land on conda in the future.\n\n# Usage\nLet us assume you have a python script that resembles to:\n```python\nfrom random import random\ndef messy_code(a):\n    print('Crazy python stuff here {}'.format(a))\n# Sorry for trolling\nmy_params = random() \nmessy_code(my_params)\nmy_params_2 = random()\nmessy_code(my_params_2)\n```\nYou run this script several times per day and you need to keep track of what is happening.\nHere it comes logpose.\n```python\nimport logpose as lp\n# Create your logpose\nmy_logpose = lp.Logpose('My Simulation', 'Try to rule the world')\n# Add a trace\nmy_logpose.add_route('Preprocessing', 'Kill all the enemies')\nmy_params = random()\n# Keep track of your input parameters\nmy_logpose.add_parameter('Preprocessing', ('my_params', my_params))\nmessy_code(my_params)\n# Get some benchmarks\nmy_logpose.bench_it()\nmy_logpose.add_trace('Prototype', 'Conquer the Russia')\nmy_params_2 = random()\nmy_logpose.add_parameter('Prototype', ('my_params', my_params_2))\nmessy_code(my_params_2)\nmy_logpose.bench_it()\n```\nYou only need the patience of changing the `'description'` parameter in `Logpose('name', 'description')` at each run, to make the logpose meaningful (for you) in the future.\nInfact, at each run logpose saves a YAML file in the folder **.lp/{name}** of your project.\n\n# More details\nA jupyter notebook containing a script for data science can be summarised in:\n1. **ETL**: retrive data from the source, loading data, feature selection, feature construction, etc.\n2. **ML Model**: construction of the train, test set, adoption of serveral ML algorithms, cross validation \n3. **Results**: analysis over the metrics obtained via the previous step\nThis script might change several times, even during the same day. The dataset as well might change.\n\nWhenever you run the script you have to keep track of many variables such as: the number of records in the dataset, the feature selected, the features constructed, the hyper-parameters of the ML algorithm, the metrics and so on.\nLogpose creates a folder where all these information will be stored into YAML files and grouped by simulation name, which can be viewed and compared later on.\n\n### The code\nThe logpose module contains mainly two relevant classes:\n- `Logpose` generates logs with the help of its methods,\n- `History` access the logs created via a `Logpose` object.\n\nLet us assume we have a jupyter representing a simulation with a xgboost algorithm.\n\n#### Logpose object\nThe `Logpose` object is a container which creates a folder named with the same name given to the object.\n```python\nimport logpose as lp\n# Create your logpose\nmy_logpose = lp.Logpose('xgboost', 'Attempt number 1 with xgboost, max_depth = 15')\n```\nThe code above creates the path `/lp/xgboost` in the directory where the code file is located.\n\nSince a `Logpose` instance is just an empty box, it is necessary to add task to log. A task is a unit piece of code to log, and in the framework of **logpose** is called a `Route`. A `Route` be created by calling the `add_route()` method.\n```python\nimport logpose as lp\n# Create your logpose\nmy_logpose = lp.Logpose('xgboost', 'Attempt number 1 with xgboost, max_depth = 15')\n''' CODE MISSING '''\nmy_logpose.add_route('Model', 'No cross validation')\nimport xgboost as xgb\nparam = {'max_depth': 2, 'eta': 1, 'silent': 1, 'objective': 'binary:logistic' }\nnum_round = 2\nbst = xgb.train(param, dtrain, num_round)\nmy_logpose.bench_it('Model')\nmy_logpose.save()\n''' CODE MISSING '''\n```\nThe code above shows how to create a `Route` and how to close it via the method `bench_it()`.\nTo summarise, the methods `add_route()` and `bench_it()` are respectively the opening and closing tag, wrapping the code we aim to log.\n\nNow, the `Logpose` instance is aware of a task to log and it is also timing it. The code written above, would create a log file in the folder **./.lp/xgboost** in which are stored the description of the `Logpose`, the characteristics (name and description) of the `Route` and its execution time. The file is saved once the meth `save()` is called.\nIn order to track also the xgboost parameters, we have to use the method `add_parameters()`.\n```python\nimport logpose as lp\n# Create your logpose\nmy_logpose = lp.Logpose('xgboost', 'Attempt number 1 with xgboost, max_depth = 15')\n''' CODE MISSING '''\nmy_logpose.add_route('Model', 'No cross validation')\nimport xgboost as xgb\nparam = {'max_depth': 2, 'eta': 1, 'silent': 1, 'objective': 'binary:logistic' }\nmy_logpose.add_parameters('Model', param)\nnum_round = 2\nmy_logpose.add_parameters('Model', ('num_round', 2))\nbst = xgb.train(param, dtrain, num_round)\nmy_logpose.bench_it('Model')\nmy_logpose.save()\n''' CODE MISSING '''\n```\nIn this way also the parameters (`param` and `num_round`) would get saved inside the logfile.\n\nLinked to the same logpose instance you can add multiple routes, structuring the log in the way you like. For example, following the scheme described above:\n\n```python\nimport logpose as lp\n# Create your logpose\nmy_logpose = lp.Logpose('xgboost', 'Attempt number 1 with xgboost, max_depth = 15')\nmy_logpose.add_route('Preprocessing', 'Remove missing values')\n''' CODE MISSING '''\nmy_logpose.bench_it('Preprocessing')\nmy_logpose.add_route('Model', 'No cross validation')\nimport xgboost as xgb\nparam = {'max_depth': 2, 'eta': 1, 'silent': 1, 'objective': 'binary:logistic' }\nmy_logpose.add_parameters('Model', param)\nnum_round = 2\nmy_logpose.add_parameters('Model', ('num_round', 2))\nbst = xgb.train(param, dtrain, num_round)\nmy_logpose.bench_it('Model')\nmy_logpose.add_route('Results', 'Metrics over train and validation sets')\n''' CODE MISSING '''\nmy_logpose.bench_it('Results')\nmy_logpose.save()\n```\n\n#### History object\nIf you want to check what happened in a simulation where you have used a `Logpose`, you just need to check in the **./.lp** folder. \nAlternatively, it is possible to create a `History` object.\n```python\nhistory_log = lp.History('xgboost')\nmy_simulations = history_log.events\n```\nThe `History` attribute `events` provides the list of all the YAML files located in the logpose folder **./.lp/xgboost/**. To load an event:\n```python\nimport pandas\nlogpose_info, logpose_df = history_log.load_event(my_simulations[0], pandas = True)\n```\nWhen the `pandas` parameter is `True`, the method `load_event()` returns 2d-tuple where the second element is a pandas dataframe.\n\nTo compare all the events, the log files stored in the folder, you can use the method `compare()`.\n```python\nhistory_df = history_log.compare(pandas = True)\n```","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsaleepeppe%2Flogpose","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fsaleepeppe%2Flogpose","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsaleepeppe%2Flogpose/lists"}