Creating a Packageable App With uv
00:00 Now that you’ve built your package and you’ve seen how to specify entry points manually in your project and how to specify a build system, you’ll learn how to do that in a more automatic way.
00:13
So when you initialize your project, if you already know you want to make it packageable so that you can build it and then share it, you can use the option --package
with the command uv init
, and that will tell uv
to specify a build system in your pyproject.toml
file.
00:33
And that’s in opposition to using the option --no-package
, which you will also say explicitly, I don’t want a package. So --package
is very useful for this project.
00:44
And similarly, if you know you are building a packageable app, you can use the option --app
which sets up the entry point section for you. And this is in opposition to using the option --lib
, which tells uv
, you’re specifying a project that will contain modules that others will import, as opposed to run directly, like in the case of a CLI or a web server or something that you typically want to run.
01:13
So the options --package
and --app
are very useful in this case. So let’s see how you could use them. Go ahead and open the terminal. Make sure you’re inside your projects, and if you list the contents of your project, you will see a couple of files you already know, a couple of directories that were created in the previous lesson when you were building your project.
01:37
So what you’ll want to do now is get rid of all of these directories that were created because of the building process, because we want to reset some parts of the uv
configuration so you can see how to do that automatically.
01:50
So go ahead and remove the directory __pycache__/
01:54
with the double underscore, remove the folder or the directory dist
, and also the rpcats.egg-info
. So remove those three. Do it however you want.
02:04
I just use the command rm
, and once you do that, your project will be cleaner. And now the pyproject.toml
file is what tells uv
that you have a project.
02:16 So if you go ahead and delete it,
02:20
uv
no longer sees this directory as a project. So make sure you completely delete the file pyproject.toml
because once you do that, you can use the command uv init
again to initialize these projects.
02:36
So go ahead and run the command uv init
.
02:40
Now, because you’re already inside the directory that holds your project, you do not need to specify the project name. So just type uv init
, and now you’ll want to use these options that you just learned about, namely --package
, so that uv
defines a build system for you, and --app
so that uv
defines entry points for you.
03:03
And then let’s say you want this to be a Python 3.13 project, and if you press Enter, uv
tells you it initialized a project rpcats
.
03:12 Notice how it inferred the name of the project from the name of the folder it’s in. If you list the contents of your directory again,
03:21
you will see that the file pyproject.toml
was re-created. And if you go ahead and open it, you will see that uv
created the section [project.scripts]
and also a section [build-system]
.
03:37
And you can even notice that by default, uv
uses a build system different from what you just used in the previous lesson, but that’s okay, don’t worry about it.
03:46 It’s just a good example of how there are different build systems.
03:50
If you go back to your terminal, you might also notice that uv
created a directory source/
. And that’s because when you specify that you’re building a packageable app, uv
assumes you’ll want to use a slightly different layout instead of the 100% flat layout you had before.
04:10
So if you use the command ls -R
and the -R
stands for recursive, you’ll be listing recursively the contents of your directory, and you can see that there’s the src
directory that uv
created for you.
04:25
This src
directory in turn contains a directory called rpcats/
, which matches the name of your project. And inside rpcats/
you have a file __init__.py
.
04:35
And this file __init__.py
contains a small stub main()
function like it did in the beginning. So if you take a look at that file, if you cat the contents of that file, you will see that it contains a call to the print()
function inside of main()
.
04:54
That’s just a stub file so that you could try and run your projects right away. In fact, you can run uv run rpcats
05:03
and it automatically goes through the build process and it runs your main()
function. It calls your print()
function and prints Hello from rpcats!
But what you want to do is actually you want to tweak this entry point so that it runs your code, the code you have.
05:20 So let’s go ahead, clear the screen,
05:23
and if you list the contents of your directory, just in case you forgot, your code lives in this file main.py
. So what you’ll do now is if you were creating your project from scratch, you will be writing the code directly in the correct place.
05:36
But for now, what you’ll do, because we’ve reinitialized the project, is move the file main.py
into the src/
rpcats/
directory.
05:48
And once it’s there, if you list the contents of the directory src/rpcats
, you see the __init__.py
file that was created by uv
and your main.py
.
06:00
So now what you want to do is you want to fix the entry points to run your code instead of the stub. So open up the pyproject.toml
file.
06:09
And if you look at your entry points, this specifies the rpcats/
folder inside the src
directory. And the colon main
specifies the main()
function.
06:20 And this by default, this assumes you’re talking about the
06:24
__init__.py
file, but you want to run code in your main.py
file. So you need to edit the entry point, and you do that by doing a .main
.
06:34
So now you are saying that you want to look at the file main
inside the folder rpcats/
, and then the colon main
specifies the function main()
.
06:46
So save your pyproject.toml
, go back to your terminal, and if you run uv run rpcats
,
06:57 it will run your CLI and you’ll see here you have an error because you didn’t specify a breed. So now you can get some information on a cat breed.
07:09
So this was a bit longer than required because you already have almost everything in your projects and so you just deleted some configuration parts, so you could see how uv
does this automatically.
07:22 What’s very important to realize is that you could have done this from the very beginning, and you would’ve had the correct or an appropriate or a useful source layout from the beginning and you would’ve had the entry points and the build system also specified from the beginning.
07:40
So when you create new projects, consider whether you want to use --package
or not, and consider whether you want to use --app
or --lib
, which you didn’t see in this lesson.
07:53
I hope that at this point you are super excited about uv
. uv
has lots of features, lots of subcommands you’ve explored, some of them, you’ve learned about some very useful subcommands, but there’s a lot that uv
can do.
08:07 So hopefully you have the interest in going off on your own and figuring all of this out. And before we wrap up this course, I just have a couple of extra resources to share with you in the next lesson.
Become a Member to join the conversation.