Using Temporal

3/8/2023

Python SDK: Your First Application

Rain Leander Headshot

Rain Leander

Developer Advocate

I wanna hold ‘em like they do in Texas, please

python-social

In previous posts my colleagues dug into why we built the Python SDK, workers and workflows, but what does that look like in practice? Maybe you’re the type of person who has read the articles, perused the Developer’s Guide, taken a look at the Python SDK sample apps, and thought, “This is too much!”

Wanna bet?

My role as a developer advocate is to explore the SDK a bit more and see how to bring it to life in different ways and this post is meant to be a peek into my own Temporal learning journey.

Personally, I am the type of person who prefers to DO the thing rather than read about or hear about the thing. So, while documentation and videos are vital to my learning experience, the “aha” moment doesn’t all click into place until I actually get my hands dirty.

Further, I’m the type of person who loves games and puzzles and riddles and such and I tend to turn any task into some sort of adventure.

So while there are many different examples of Temporal that are interesting to others, like a background checker, that is absolutely not my cup of tea.

I’d rather build a game.

While I knew I wanted to build a game, I wasn’t sure which one to do, but after looking closely at poker, I appreciated that the betting and money transfer would best highlight Temporal’s consistent, secure executions while taking turns highlights signals and queries.

So I built a poker application.

To enable a true user experience from having something existing and adding in Temporal afterwards, I built a simple application without any Temporal framework whatsoever.

Keep It Simple

Let’s imagine that you’re learning a new technology like Temporal, I am not going to take that new technology - AND add a database I’ve never worked with AND deploy on a platform I’ve never touched AND build an elaborate application; I want to keep the new technology as streamlined as possible, using supplemental technologies that I’m very comfortable with so that when errors pop up, I’ll know immediately if it’s related to the new technology or an old familiar pain point.

If the new technology is like a bicycle wheel, I want to explore it spoke to spoke rather than replacing the whole wheel or bike, so I can get really familiar with how things work before I take it on the road.

Temporal as a platform is robust and has a ton of powerful features, as such, it’s not a plug-and-play as you may see with some other SDKs - you can’t just import the library and go. Following our previous posts, we know that we need to:

  • Import Temporal and asyncio packages
  • Connect to the Temporal Server
  • Enable a worker
  • Create a workflow
  • Create an activity

There are many paths to bring this together, but following our recommendations may help you with some stumbling blocks. The next version of this poker application will have many more workflows, child workflows, possibly another activity, and play with signals and queries, but for v1.0, I added one simple workflow and one activity.

What does that look like in a poker game?

Let’s start with a simple workflow:

    @workflow.defn
    class PokerWorkflow:
       @workflow.run
       async def run(self) -> None:
   return await workflow.execute_activity(
       poker_game,
       start_to_close_timeout=timedelta(seconds=10),
   )

Given this is an experiment in learning Temporal and not necessarily in implementation, I used an activity to run the main part of the application:

    @activity.defn
    async def poker_game() -> None:

Please note that this is NOT a great use of Temporal - ideally this section would go only around the shuffle bit of the app because this is where the random library is used. I’ll shift it in the next version of the application.

Studio Project

Charmed by PyCharm

In my heart of hearts, I am a Vim person (sorry, not sorry, Emacs) and when I started on this project, I wrote the entire application in Python in Vim.

But once I started implementing the Temporal aspects of connecting to the server, enabling a worker, creating a workflow and such, I couldn’t tell if the error messages were from Python or Temporal or the network and an IDE cuts down on a lot of the noise.

Because I was working in the Python programming language, I turned to one of the more commonly used IDEs, PyCharm which allows you to add the Temporal modules with a few easy steps.

Use the Python Packages tool to add the temporalio package to your current project via View | Tool Windows | Python Packages. Click the Install button in the upper right hand corner of the window - the latest version is installed by default.

Screenshot 2023-03-03 at 17.51.33

PyCharm will confirm when it’s installed via a small pop up window in the lower right hand corner of the screen.

Screenshot 2023-03-03 at 17.51.43

Ask The Question

Ask for help and yes, we have Slack, but we’d like your questions to be retained for future use, so please please please use our forum and remember to ask a troubleshooting question by stating what you’re trying to do, the specific steps to do it, the expected result, and the actual result.

Or, like me, just ask the question.

Screenshot 2023-03-03 at 17.52.00

Next Steps

I hope this helps you get started with the Temporal Python SDK but if not, I’ll see you on the forum and if you’re keen to look at version 1.0 of my own poker application, feel free. For me, the next steps in learning Temporal are to dive into child workflows, signals, and queries to the poker application.

And share the next few tips and tricks I discover along the way with you.

In the meantime, what are your favorite tips and tricks as you’re getting started with Temporal? Or the Python SDK specifically? Did you program your application first and then apply Temporal or write your new application within a Temporal format from the start?

Inquiring minds want to know.

And be sure to check out the fourth blog post in this celebration of the Python SDK, Temporal Python 1.0.0 – A Durable, Distributed Asyncio Event Loop!