Recently, I was reading The Pragmatic Programmer, and the section on continual learning, especially learning how to use new tools, really stuck with me.
With that in mind, I turned my attention to ways to improve my process for starting up a new project, which is something I do fairly often to experiment.
There are several aspects of setting up a new project, and managing all of them manually can be repetitive, error-prone, and difficult. Some of the ones I wanted to take care of using tools include:
- Structuring the project directory structure
- Creating a virtual environment and activating it every time
- Managing dependencies
The tools I decided to use are poetry and vox/autovox. Poetry takes care of a lot of project management issues, while vox allows me to use virtualenvs that play well with Xonsh. In the future, I’d also like to explore using cookiecutter for templates.
I tied all of these tools–of course, plus git–together into a Xonsh alias. If you’re not familiar with that, check out my introduction to Xonsh and my article about using an alias to filter Mut.py results.
xontrib load vox, autovox from pathlib import Path def _create_project(args): project_name = args[0] poetry config virtualenvs.create false poetry new @(project_name) cd @(project_name) env_name = str(Path.cwd())[1:] print("Removing previous virtualenv, if it exists (KeyError means that it did not exist)") vox deactivate vox remove @(env_name) pyenv_path = Path($(pyenv root).strip()) / "versions" interpreter = $(pyenv version-name).split(":")[0] interpreter_path = str(pyenv_path / interpreter / "bin" / "python") print("Using Python " + interpreter + " at " + str(interpreter_path)) vox new @(env_name) --interpreter @(interpreter_path) git init rm pyproject.toml poetry init aliases["create_project"] = _create_project @events.autovox_policy def auto_based_on_dir(path, **_): venv = Path($HOME + "/.virtualenvs" + str(path)) if venv.exists(): return venv
The usage is simple: $ create_project project_name
will use poetry to create a new project directory project_name
, then creates an environment, initializes the git repository, removes the pyproject.toml
made by poetry new
, and finally runs poetry init
to interactively create a new pyproject.toml
.
Most of this is pretty simple, but it takes care of several steps at once with one command, which allows me to jump right in to coding when I have a new idea or want to experiment with something.
The most complicated part is the creation of the virtual environment and registering an autovox policy to automatically activate the environment. Vox creates all virtual environments in ~/.virtualenvs
. So, for example, if I start a project in /home/harrison/project_name
, then a virtual environment gets created at ~/.virtualenvs/home/harrison/project_name
.
The auto_based_on_dir
function gets registered with autovox and controls activating the proper environment based on what directory I’m working on. It does this by checking whether a virtual environment based on a particular path exists, and returns the path to it if it does.
Conclusion
I’m excited to continue to improve the tools I use in my projects. In particular, poetry seems like a good way to manage and publish projects to the PyPI. It only took a little bit of time to put this together, and I expect it will result in a lot of good.
Switching to vox and using autovox to activate virtual environments should also save a lot of time. In the past, I’ve used pyenv virtualenv
and manually activated environments as needed.
What tools do you use as part of your workflow?