<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom">
 
 <title>Matt Thompson</title>
 <link href="" rel="self"/>
 <link href=""/>
 <updated>2025-05-19T09:48:40-07:00</updated>
 <id></id>
 <author>
   <name>Matt Thompson</name>
   <email>matt.thompson@openforcefield.org</email>
 </author>

 
 <entry>
   <title>A swiss army knife for conda issues - re-create your environment</title>
   <link href="/posts/2025/02/recreate-conda/"/>
   <updated>2025-05-19T00:00:00-07:00</updated>
   <id>/posts/2025/02/recreate-conda</id>
   <content type="html">&lt;h2 id=&quot;delete-your-conda-environments-often&quot;&gt;Delete your conda environments often&lt;/h2&gt;

&lt;p&gt;Here, I’ll be making the case that deleting and re-creating your conda environments is a best practice to do every once in a while and also something to frequently reach for when things look off. This doesn’t solve every problem, but it works more often than you might expect.&lt;/p&gt;

&lt;p&gt;It’s also commonly the first step in producing a high-quality issue and, for “ghost in the machine” types of problems, can save potentially hours of human time. The trade-offs of a few minutes’ investment are pretty good.&lt;/p&gt;

&lt;h2 id=&quot;no-really-theyre-meant-to-be-deleted&quot;&gt;No, really, they’re meant to be deleted&lt;/h2&gt;

&lt;p&gt;The point of virtual environments (a category of tools that includes conda environments) is to isolate library and application versions used in a specific project from everything else on your system. Python practitioners do this so often we may take for granted how cool this is - we can safely test out different versions of software in an isolated corner of a harddrive without committing to changing anything outside of it.&lt;/p&gt;

&lt;p&gt;A feature of virtual environments is that they’re easy to create. If it took as long to try out the newest Python release as it did to install a fresh operating system or start a new virtual machine, there wouldn’t be much of a point to it. The flipside of this is that virtual environments are also eminently deletable. &lt;strong&gt;Easy to create, easy delete.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Another implementation detail: the environments are stored separately from the virtual environment manager itself and all of its configs, cache, etc. So deleting an environment &lt;strong&gt;does not&lt;/strong&gt; delete your conda/mamba/micromamba/etc installation.&lt;/p&gt;

&lt;h2 id=&quot;how-to-delete-your-conda-environments&quot;&gt;How to delete your conda environments&lt;/h2&gt;

&lt;p&gt;It’s as simple as finding where your conda environment is stored - probably at &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;$CONDA_PREFIX&lt;/code&gt; - and blow it away. Just remove it.&lt;/p&gt;

&lt;p&gt;For example, I was most recently working on something in an environment named &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;interchange-examples-env&lt;/code&gt; which is tracked by a file in the path &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;devtools/conda-envs/examples.yaml&lt;/code&gt;. I use &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;micromamba&lt;/code&gt; which is installed on this machine at &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/Users/mattthompson/micromamba/&lt;/code&gt; - your setup might differ slightly but &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;$CONDA_PREFIX&lt;/code&gt; should point to your current environment. Like so:&lt;/p&gt;

&lt;div class=&quot;language-console highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;gp&quot;&gt;$&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;echo&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$CONDA_PREFIX&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;/Users/mattthompson/micromamba/envs/interchange-examples-env
&lt;/span&gt;&lt;span class=&quot;gp&quot;&gt;$&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;rm&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$CONDA_PREFIX&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;$&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;micromamba create &lt;span class=&quot;nt&quot;&gt;--file&lt;/span&gt; devtools/conda-envs/examples_env.yaml &lt;span class=&quot;nt&quot;&gt;--quiet&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;Confirm changes: [Y/n] y
warning  libmamba [xorg-libx11-1.8.10-h6a5fb8c_1] The following files were already present in the environment:
    - include/X11/Xlib.h
    - include/X11/Xutil.h
    - include/X11/cursorfont.h
warning  libmamba [openff-interchange-base-0.4.1-pyhd8ed1ab_0] The following files were already present in the environment:
    - lib/python3.12/site-packages/docs/conf.py
warning  libmamba [openff-nagl-base-0.5.1-pyhd8ed1ab_0] The following files were already present in the environment:
    - lib/python3.12/site-packages/docs/conf.py
&lt;/span&gt;&lt;span class=&quot;gp&quot;&gt;$&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;micromamba activate interchange-examples-env
&lt;span class=&quot;gp&quot;&gt;$&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;micromamba list  &lt;span class=&quot;c&quot;&gt;# or whatever command to verify the result&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;...
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;I timed this and it took about 100 seconds. This environment is particularly bulky with several large packages; other environments should take much less time to re-create. For smaller environments, think along the lines of 5 or so seconds.&lt;/p&gt;

&lt;h2 id=&quot;more-reasons-to-delete-your-conda-environments&quot;&gt;More reasons to delete your conda environments&lt;/h2&gt;

&lt;h3 id=&quot;virtual-environments-can-carry-historical-cruft&quot;&gt;Virtual environments can carry historical cruft&lt;/h3&gt;

&lt;p&gt;It’s hard to be more specific because of the range of things that can happen when updating conda environments, switching Python versions, or blindly copying installation instructions (no shame, I do this myself). I also don’t fully understand the ways that constraints and various configs can persist in environments (and some of these interactions are probably bugs).&lt;/p&gt;

&lt;h3 id=&quot;re-creating-your-environment-syncs-your-development-with-the-environment-file&quot;&gt;Re-creating your environment syncs your development with the environment file&lt;/h3&gt;

&lt;p&gt;It’s easy for the contents of your environment to diverge from what’s encoded in your environment. It can start with an innocuous-seeming change to one package’s version but over time grow to include changes to several packages’ major versions. As these changes accumulate, you start to lose track of important details such as why they were made and whether or not some packages are incompatible with each other. Environment files easily capture this on disk on disk in a standardized format (YAML is more standardized than a string of shell commands) which can be tracked with version control. You can, and probably should, pepper this file with comments explaining, for example, why particular version constraints are included or when a particular pin might be removable (“let OpenMM 8 be installed when X plugin is updated …”)&lt;/p&gt;

&lt;p&gt;This can be done with &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;mamba env update ...&lt;/code&gt; but going all the way to re-creating a an environment better represents the contents of the environment, i.e. it “forgets” the other modifications that you may have made. (If you do want to make changes, you should make them to the environment file directly, since that’s the best record of what you intend to be there.)&lt;/p&gt;

&lt;p&gt;If all of this seems to you like a nuisance - you’re not alone! Keeping a project environment and its environment specificaiton &lt;em&gt;always&lt;/em&gt; and &lt;em&gt;automatically&lt;/em&gt; in sync is the basic pitch of &lt;a href=&quot;https://pixi.sh/latest/&quot;&gt;Pixi&lt;/a&gt;. I think &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;uv&lt;/code&gt; and some &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;pip&lt;/code&gt;-adjacent tools have similar features, but haven’t used them myself.&lt;/p&gt;

&lt;h3 id=&quot;its-whats-going-to-happen-when-deploying-your-product&quot;&gt;It’s what’s going to happen when deploying your product&lt;/h3&gt;

&lt;p&gt;No matter where your script or package ends up after you’re done with it, an environment will be re-created from scratch later on.&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;If you’re collaborating with somebody on a shared project, their first step will probably be making a conda environment.&lt;/li&gt;
  &lt;li&gt;If you’re deploying an app to the cloud or firing off huge production runs to HPC, it’s the same story.&lt;/li&gt;
  &lt;li&gt;If you’re developing a software package, bots in the form of CI runners will do this frequently.&lt;/li&gt;
  &lt;li&gt;f you’re a solo researcher working on a project that can be started and completed on your workstation, somebody trying to reproduce your findings will start by (you guessed it!) re-creating the environment.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3 id=&quot;its-the-first-step-in-submitting-a-bug-report-anyway&quot;&gt;It’s the first step in submitting a bug report, anyway&lt;/h3&gt;

&lt;p&gt;Remember that devising a minimally reproducible example is central to making a high-quality bug report - if the behavior can’t be reproduced on a new machine, &lt;strong&gt;it effectively doesn’t exist&lt;/strong&gt;. The first thing a maintainer (or bot!) will do in trying to diagnose your possibly-buggy finding is reproduce the behavior of interest. In order to do this, essentially the zeroth step, they will need to install versions of all relevant software on their machine, a.k.a. re-creating your environment. In submitting a bug report, you might as well do this yourself to verify that the maintainer will see what you predict they’ll see.&lt;/p&gt;

&lt;h3 id=&quot;it-shouldnt-take-long-to-re-create-the-environment&quot;&gt;It shouldn’t take long to re-create the environment&lt;/h3&gt;

&lt;p&gt;I can hear this concern because it was my internal dialogue &lt;em&gt;for ages&lt;/em&gt; -  “it’s too risky for me to re-create this environment, the current version constraints are going to make impossible to solve!” These days, with rare exceptions, that’s no longer the case. It’s true that Conda environments were often slow - even unusably slow - to solve many years ago. (In packaging jargon, “solving” or finding a “solution” is the process by which the package manager finds versions of every package that satsfies the requirements, probably communicated in an environment YAML file.) These days, environments take a few seconds to solve - gone are the days of watching &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;conda&lt;/code&gt; spin its wheels for 20 minutes and get nowhere. These tools also make use of caching under the hood so that many steps (i.e. downloading tarballs) are often skipped when creating an environment the second time.&lt;/p&gt;

&lt;h3 id=&quot;an-aside---mambamicromamba-are-great-but-conda-is-fine&quot;&gt;An aside - Mamba/micromamba are great, but conda is fine&lt;/h3&gt;

&lt;p&gt;Mamba came into existence in large part out of a desire to re-write Conda’s solver from the ground up in C++ while maintaining a similar user experience. It has some rough edges 5+ years ago but now (in mid 2025) the community has accepted it for general use. Its solver, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;libmamba&lt;/code&gt;, was even &lt;a href=&quot;https://www.anaconda.com/blog/a-faster-conda-for-a-growing-community&quot;&gt;integrated into &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;conda&lt;/code&gt; itself&lt;/a&gt; a few years ago and later &lt;a href=&quot;https://conda.org/blog/2023-11-06-conda-23-10-0-release/&quot;&gt;the default&lt;/a&gt;. I still recommend using &lt;a href=&quot;https://mamba.readthedocs.io/en/latest/&quot;&gt;Mamba&lt;/a&gt; or its slimmed-down drop-in replacement &lt;a href=&quot;https://mamba.readthedocs.io/en/latest/user_guide/micromamba.html&quot;&gt;Micromamba&lt;/a&gt;, but if you see teammates using &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;conda&lt;/code&gt;, don’t automatically assume that they’re using the same tool you were frustrated by in 2019. It’s much-improved across the board thanks to a monumental and sustained volume of effort from volunteer contributors in the conda orbit. Some companies have also made significant contributions: Anaconda, Inc., Quansight, QuantStack, and prefix.dev immediately come to mind, but I’m sure I’m forgetting some.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Six steps to success when reporting open-source computational chemistry issues</title>
   <link href="/posts/2025/01/issues/"/>
   <updated>2025-01-03T00:00:00-08:00</updated>
   <id>/posts/2025/01/issues</id>
   <content type="html">&lt;p&gt;I’ve been working with open-source computational chemistry tools for about a decade, half of which has been in a professional capacity. I’ve worn about every hat - developer, maintainer, confused user, poweruser, typo-producer, and combinations thereof - so I’ve become more familiar &lt;a href=&quot;https://xkcd.com/2347/&quot;&gt;with how the sausage is made&lt;/a&gt; than I maybe originally hoped to.&lt;/p&gt;

&lt;p&gt;A persistent problem in this space is a mismatch between the supply and demand of maintenance: users, especially of popular and valuable libraries, have feature requests and bug reports, but maintainers are almost universally stretched thin on both time and attention. I’ve been on every side of this - a maintainer who falls behind his responsibility, a user who reported bugs to un-maintained projects, a developer who contributed patches to projects that were on their path to abandonment, the list goes on.&lt;/p&gt;

&lt;p&gt;Below are a few steps that at best can resolve issues without needing to get a maintainer’s attention and at worst make it as easy as possible for them to help. They are ordered intentionally and could serve as either a programmatic checklist to work through while figuring out a bug or as a general framework in which to think about communicating them.&lt;/p&gt;

&lt;h2 id=&quot;check-to-see-if-the-project-is-active&quot;&gt;Check to see if the project is active&lt;/h2&gt;

&lt;p&gt;It’s an awkward discovery to make, but it happens occasionally. The tool you’ve been using for a while, or maybe even built a business-critical product out of, hasn’t had a release in a while. You’re worried it’s completely abandoned. There’s unfortunately no clear boundary between a project being only a little dusty and simply too rusty to use. The three things I look for, and general timeframes, are&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Any commits in the past year, even ones that look trivial or are authored by bots.&lt;/li&gt;
  &lt;li&gt;Any activity in the past two years from maintainers/authors on GitHub, even if it’s only an apology that they’re behind on things.&lt;/li&gt;
  &lt;li&gt;Any releases in the past three years, a rough time period after which a release is unlikely to work with new upstreams.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Sometimes a project can be sunset for good reasons, such as &lt;a href=&quot;https://github.com/pre-commit/action&quot;&gt;being replaced by something newer and better&lt;/a&gt;. More commonly, the maintainers have moved on and either signaled the end of the project or no intent to add or welcome new features. No matter the reason, the top of the README file is the place to check. Precisely what to do if a project is pushed into maintenance-only mode is trickier topic and a discussion for another day. But if there is a signal, explicitly or implicitly, that the project is not being maintained, there is less reason to continue through the next steps.&lt;/p&gt;

&lt;h2 id=&quot;search-the-documentation&quot;&gt;Search the documentation&lt;/h2&gt;

&lt;!---

Human time is almost universally more expensive than computer time, be it measured by the cost of serving webpages, re-running calculations in examples, or explaining the problem a tool aims to solve. A key reason that it&apos;s worth it for developers to spend time writing documentation instead of building more tools, in my opinion, is so that their expertise can be scaled out to a large user base without the need to personally interact with every user.
---&gt;

&lt;p&gt;Hopefully the tools you’re using have some documentation, even if it’s only automatically-generatic or hastily-written code snippets in a README file. No matter what shape it takes, it’s there to be used; the cost that developers (and organizations more broadly) sink into writing and providing documentation is done with the intention that it enables you to use the software with minimal friction. It’s usually built up over time as incremental responses to user feedback and support requests, so common use cases are more likely to be included in example code and prose. This is especially true for older and more mature libraries. For example, loading a SMILES string is basically at the top of &lt;a href=&quot;https://rdkit.org/docs/GettingStartedInPython.html&quot;&gt;RDKit’s documentation&lt;/a&gt;, so even a non-chemist can learn how to do that without digging into the guts of the toolkit.&lt;/p&gt;

&lt;p&gt;The documentation should be easily accessible, i.e. one click from a GitHub landing page. (If it’s not, or if a link is broken/outdated, the maintainers would probably like to know!) Hopefully it has features such as a navigation pane to organize common topics and a search bar to find something by keyword. It’s natural to reach for Google to search across other websites, but be aware that it likes to index and provide &lt;a href=&quot;https://github.com/openmm/openmm/issues/3992&quot;&gt;old versions of documentation&lt;/a&gt;, even if it’s years out of date and no longer accurate.&lt;/p&gt;

&lt;h2 id=&quot;search-for-existing-issues&quot;&gt;Search for existing issues&lt;/h2&gt;

&lt;p&gt;Users (like you!) are often doing exotic and novel things, especially in open-source computational chemistry which is populated by people who want to push the edges of what’s possible. Sometimes, however, somebody else out there has tried what you’re trying to do and has left a paper trail on GitHub. Older and/or closed issues likely include discussion from maintainers and other users that is helpful. Frequently, older issues don’t precisely match what the user is after but provides some useful context or code snippets that can be adapted to a new use case.&lt;/p&gt;

&lt;p&gt;GitHub’s default search tool works fine for this. I don’t recommend using LLMs for this, currently, as training data is sparse and hallucinations are common and harmful.&lt;/p&gt;

&lt;p&gt;Even if you’re coming across a corner case that is completely new, signaling to maintainers that you made an effort to search for existing issues is an easy way to build goodwill. (Think “I searched for ‘foo’ and ‘bar’ but couldn’t find any prior discussion of combining it with ‘baz’, so … “.)&lt;/p&gt;

&lt;h2 id=&quot;attempt-to-isolate-the-behavior-in-a-fresh-environment&quot;&gt;Attempt to isolate the behavior in a fresh environment&lt;/h2&gt;

&lt;p&gt;Even when working in virtual environments (synonymously conda environments), it’s easy for local versions of libraries to diverge from released versions. This is especially common when working with unreleased software, such as installing against a &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;git&lt;/code&gt; repo or developing off of feature branch(es).&lt;/p&gt;

&lt;p&gt;Virtual environments are designed to be created quickly and easily. This means the cost of deleting and re-creating an environment should be trivial. Try reproducing the error in a fresh environment; if the issue persists, it’s likely to be genuine. Sometimes, however, the proverbial ghost in the machine can be shooed away just by blowing away a virtual environment.&lt;/p&gt;

&lt;h2 id=&quot;produce-a-minimal-reproducible-example&quot;&gt;Produce a minimal reproducible example&lt;/h2&gt;

&lt;p&gt;If the issue appears to be new and can be reproduced in a fresh virtual environment, try to wrap it into a self-contained example, or minimal reproducing example (MRE). The goal is to isolate the problematic behavior (reproduce) with as little code as possible (minimal) and can usually be done in a single script (example). This is standard practice in the field, so &lt;a href=&quot;https://stackoverflow.com/help/minimal-reproducible-example&quot;&gt;plenty is already written about it&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;This may seem like duplicated effort (I just showed the error, isn’t that enough?) but for a maintainer to dig into the root cause of an issue, they need to be able to get to your state on their machine. This is only possible by installing the versions of libraries you used and running a script(s) that reproduce the problematic behavior in a self-contained manner. Think about coming into the problem but without the time spend to get there; the maintainer is playing catch-up to everything you’ve doing before discovering the bug.&lt;/p&gt;

&lt;h2 id=&quot;remember-the-human&quot;&gt;Remember the human&lt;/h2&gt;

&lt;p&gt;Most open-source tools are maintained by people who are not - and have not, and likely will not ever be - paid for doing so. As is stated in most licenses, these tools are distributed for free but without warranty or guarantees of fitness. The person dealing with your bug report or feature request is likely doing so in their free time with no expectation of compensation. Even the (relatively few) people who maintain open source tools as part of their day job tend to be overburdened with other responsibilities and aren’t able to budget large portions of their working hours to issue triage, user support, and bug fixes.&lt;/p&gt;

&lt;p&gt;It may seem like each of the above steps are self-serving to open-source maintainers, simply diverting users to other solutions than directly getting their attention and support or making the users do some of the work. That’s precisely what’s going on here:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;Documentation is a cheap way of demonstrating common use cases, which are probably sufficient for a majority of the user base.&lt;/li&gt;
  &lt;li&gt;Archiving disussion (and bug reports, user support, etc.) on GitHub provides a relatively straightforward way for issues to not be re-solved repeatedly and for users (including future users) to help each other.&lt;/li&gt;
  &lt;li&gt;Re-creating creating a virtual environment is a sort of blunt-force object that can remove cruft which may be confounding the apparent issue.&lt;/li&gt;
  &lt;li&gt;Wrapping the behavior into a minimal reproducing example makes it easier - commonly, just makes it &lt;em&gt;possible&lt;/em&gt; - for maintainers to make an attempt at figuring out what’s going wrong.&lt;/li&gt;
  &lt;li&gt;Keeping reasonable expectations for support from unpaid volunteers is essential for all parties involved.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;These steps, considered after evaluating if the project is still active, should make it more likely that your issue is engaged with by maintainers. Working for the &lt;a href=&quot;https://openforcefield.org/&quot;&gt;Open Force Field Initiative&lt;/a&gt;, a project in the &lt;a href=&quot;https://omsf.io/&quot;&gt;Open Molecular Software Foundation&lt;/a&gt;, I frequently am on the receiving end of many reports from users across several project. Those which follow some of these steps are much easier to work with than those that don’t, which for practical reasons has bearing on how quickly I’m able to see them to completion. (Frequently the user actually &lt;a href=&quot;https://github.com/openforcefield/openff-interchange/issues/642&quot;&gt;does most of the work&lt;/a&gt; and I’m able to quickly turnaround a bugfix with little effort.) I’m guilty about those that I respond to later or slip through the cracks for longer - but you can use these tips to your advantage and, with some non-trivial investment in reporting the issue, keep a spot at the front of the line.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Using progressbar in Python scripts</title>
   <link href="/posts/2019/12/progressbar/"/>
   <updated>2019-12-30T00:00:00-08:00</updated>
   <id>/posts/2019/12/progressbar</id>
   <content type="html">&lt;p&gt;I often find myself running a script, usually analysis of some molecular dynamics trajectory, without knowing how long it will take. This typically for any of the following reasons:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;I need to finely sample a trajectory, i.e. calling some function on thousands of frames&lt;/li&gt;
  &lt;li&gt;I’m running a novel analysis and have not developed an intuition about how long it should take
(how well it should scale, if it is likely to encounter a memory bottleneck that makes it hard to
prototype on a MacBook, etc.)&lt;/li&gt;
  &lt;li&gt;Like above, maybe I just wrote it - and I try to ahere to the philosophy of “get it to work, then
get it to work well” (I may write about this another time, but for now I will just say &lt;a href=&quot;https://twitter.com/FRoscheck/status/1159158552298229763&quot;&gt;this
slide&lt;/a&gt;
from a talk by Stan Seibert at SciPy 2019 was formative for me) which means I’ve probably used
NumPy functions but left some other optimizations on the table.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;So I often find myself running &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;python my_cool_function.py&lt;/code&gt; and …. waiting. If it runs after a few
seconds, nothing to worry about. But if it takes a minute or two, then I can either hope it takes
only a few minutes longer or, as happens often, wait something like 15 minutes. Not great practice.
Until recently, my approach was to set some counter in the middle of the expensive part of the
script and just print stuff out:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;i = 0
num_iters = len(thing_im_iterating_over)

for var in thing_im_iterating_over:
    # Do some computations
    print(&apos;Done {} i out of {}&apos;.format(i, num_iters))
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;This works well enough for diagnosing how long my script may take - it’s easy enough to see if
it’ll take the order of minutes or hours, in which case something else in the workflow needs to
change - but isn’t very pretty. There’s nothing wrong with using print statement for debugging and
toying around, but I find myself doing this often enough I wanted to look for a prettier solution.
I’ve seen some programs (i.e. &lt;a href=&quot;https://signac.io&quot;&gt;signac&lt;/a&gt; lately, or downloading packages from
various package managers) use progressbars to inform the user of the status of an operation,
particularly long ones. Unsurprisingly, it’s fairly straightforward to do in Python, and here I am
sharing a couple ways I have used it. I used the &lt;a href=&quot;https://pypi.org/project/progressbar/&quot;&gt;package&lt;/a&gt; of
the same name, although I’m sure there are other fine options out there.&lt;/p&gt;

&lt;p&gt;The first simple example is structured like above, where we have a clear iterator (or generator, of
course) we’re iterating over and we know its length.&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;import progressbar


bar = progressbar.ProgressBar()

for i in bar(thing_im_iterating_over):
    # Do some computations
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;This will print out the progress bar to the terminal and it will update as the loop is executed.&lt;/p&gt;

&lt;p&gt;A slight variation of this I found useful was the case in which we don’t necessarily want to update
each iteration of a loop, but only want to update when some criteria in the loop was met.&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;import progressbar


pbar = progressbar.ProgressBar().start()

ts = 0
num_ts = 1500000

with open(&apos;huge_file.txt&apos;, &apos;r&apos;) as fi:
    for line in fi:
        line = line.split()
        if line[0] == &apos;TAG_I_CARE_ABOUT&apos;:
            # Do some some computations
            if ts % 1000 == 0:
                pbar.update(ts / num_ts * 100)
            ts += 1
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;What I don’t like about this approach is that I’m carrying an extra counter variable that I probably
don’t need. That aside, this has the benefit of  only updating the progress bar every few thousand
iterations of the outer &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;for&lt;/code&gt; loop. In this case, I was given a 1170315604 line text file and needed
to parse a particular comment line every few thousand lines, but even of those I only needed to
track every few thousand hits.&lt;/p&gt;
</content>
 </entry>
 
 
</feed>
