skip to navigation
skip to content

Planet Python

Last update: December 24, 2024 01:42 AM UTC

December 23, 2024


Daniel Roy Greenfeld

TIL: SequentialTaskSet for Locust

SequentialTaskSet makes it so Locust tasks happen in a particular order, which ensures your simulated users are clicking around in a more human manner at a more human pace. Attribution goes to Audrey Roy Greenfeld.

You can see it in action in the now updated previous entry on the topic of Locust for load testing.

December 23, 2024 07:03 PM UTC

TIL: Making pytest use Ipython's PDB

alias pdb='pytest --pdb --pdbcls=IPython.terminal.debugger:TerminalPdb'

Usage:

pdb tests/test_things::test_broken_thing

December 23, 2024 07:03 PM UTC

TIL: Fractional Indexing

In the past when I've done this for web pages and various other interfaces it has been a mess. I've built ungainly sort order in numeric or alphanumeric batches. Inevitably there is a conflict, often sooner rather than later. So sorting a list of things often means updating all the elements to preserve the order in the datastore. I've learned to mark each element with a big value, but it's ugly and ungainly

Fortunately for me, going forward, I now know about Fractional Indexing.

References:

December 23, 2024 07:03 PM UTC

TIL: Python Dictonary Merge Operator

The function way

Until today I did this:

# Make first dict
num_map = {
    'one': '1', 'two': '2', 'three': '3', 'four': '4',
    'five': '5', 'six': '6', 'seven': '7', 'eight': '8',
    'nine': '9'
}
# Add second dict
num_map.update({str(x):str(x) for x in range(1,10)})
print(num_map)

The operator way

Now thanks to Audrey Roy Greenfeld now I know I can do this:

# Make first dict while adding second dict
num_map = {
    'one': '1', 'two': '2', 'three': '3', 'four': '4',
    'five': '5', 'six': '6', 'seven': '7', 'eight': '8',
    'nine': '9'
} | {str(x):str(x) for x in range(1,10)}
print(num_map)

December 23, 2024 07:03 PM UTC

TIL: Python's defaultdict takes a factory function

I've never really paid attention to this object but maybe I should have. It takes a single argument of a callable function. If you put in Python types it sets the default value to those types. For example, if I use an int at the instantiating argument then it gives us a zero.

>>> from collections import defaultdict
>>>
>>> mydict = defaultdict(int)
>>> print(mydict['anykey'])
0

Note that defaultdict also act like regular dictionaries, in that you can set keys. So mydict['me'] = 'danny' will work as you expect it to with a standard dictionary.

It gets more interesting if we pass in a more dynamic function. In the exmaple below we use random.randint and a lambda to make the default value be a random number between 1 and 100.

>>> from random import randint
>>>
>>> random_values = defaultdict(lambda: randint(1,100))

Let's try it out!

>>> for i in range(5):
>>>     print(random_values[i])
>>> print(random_values)
29
90
56
42
70
defaultdict(<function <lambda> at 0x72d292bb6de0>, {0: 29, 1: 90, 2: 56, 3: 42, 4: 70})

Attribution goes to Laksman Prasad, who pointing this out and encouraging me to closer look at defaultdict.

December 23, 2024 07:03 PM UTC

TIL: How to reset Jupyter notebook passwords

jupyter notebook password

Attribution for this goes to Johno Whitaker.

December 23, 2024 07:03 PM UTC

TIL: Arity

I'm excited to have learned there's a word for the count of arguments to a function/method/class: arity. Throughout my career I would have called this any of the following:

Thanks to Simon Willison for using it in a library or two and making me look up the word.

December 23, 2024 07:03 PM UTC

TIL: Using hx-swap-oob with FastHTML

Until now I didn't use this HTMX technique, but today Audrey Roy Greenfeld and I dove in together to figure it out. Note that we use language that may not match HTMX's description, sometimes it's better to put things into our own words so we understand it better.

from fasthtml.common import *

app,rt = fast_app()

def mk_row(name, email):
    return Tbody(
        # Only the Tr element and its children is being
        # injected, the Tbody isn't being injected
        Tr(Td(name), Td(email)),
        # This tells HTMX to inject this row at the end of
        # the #contacts-tbody DOM element
        hx_swap_oob="beforeend:#contacts-tbody",
    ),

@rt
def index():
    return Div(
            H2("Contacts"),
            Table(
                Thead(Tr(Th("Name"), Th("Email"))),
                Tbody(
                    Tr(Td("Audrey"), Td("mommy@example.com")),
                    Tr(Td("Uma"), Td("kid@example.com")),
                    Tr(Td("Daniel"), Td("daddy@example.com")),
                    # Identifies the contacts-tbody DOM element
                    id="contacts-tbody",
                ), 
            ),
            H2("Add a Contact"),
            Form(
                Label("Name", Input(name="name", type="text")),
                Label("Email", Input(name="email", type="email")),
                Button("Save"),
                hx_post="/contacts",
                # Don't swap out the contact form
                hx_swap='none',
                # Reset the form and put focus onto the name field
                hx_on__after_request="this.reset();this.name.focus();"
            )
        )

@rt
def contacts(name:str,email:str):
    print(f"Adding {name} and {email} to table")
    return mk_row(name,email)

serve()

To verify the behavior, view the rendered elements in your browser of choice before, after, and during submitting the form.

December 23, 2024 07:03 PM UTC

TIL: Using Python to removing prefixes and suffixes

Starting in Python 3.9, s.removeprefix() and s.removesuffix() were added as str built-ins. Which easily covers all the versions of Python I currently support.

Usage for removeprefix():

>>> 'Spam, Spam'.removeprefix('Spam')
', Spam'
>>> 'Spam, Spam'.removeprefix('This is not in the prefix')
'Spam, Spam'

Usage for removesuffix():

>>> 'Spam, Spam'.removesuffix('Spam')
'Spam, '
>>> 'Spam, Spam'.removesuffix('This is not in the suffix')
'Spam, Spam'

December 23, 2024 07:03 PM UTC

Using locust for load testing

Locust is a Python library that makes it relatively straightforward to write Python tests. This heavily commented code example explains each section of code. To use locust:

  1. Install locust: pip install locust
  2. Copy the file below into the directory where you want to run locust
  3. In that directory, at the command-line, type: locust
  4. Open http://localhost:8089/
# locustfile.py
# For more options read the following
#   - https://docs.locust.io/en/stable/writing-a-locustfile.html
#   - https://docs.locust.io/en/stable/tasksets.html

# Import Locust basics
from locust import HttpUser, SequentialTaskSet, task, between

# Imports for generating content
from string import ascii_letters
from random import randint, shuffle

def namer():
    "Create a random string of letters under 10 characters long"
    ascii_list = list(ascii_letters)
    shuffle(ascii_list)
    return ''.join(ascii_list[:10])

class TaskSet(SequentialTaskSet):
    """
    A class for organizing tasks, inheriting from
    SequentialTaskSet means the tasks happen in order.
    """

    def on_start(self):
        # Methods with the on_start name will be called for each
        # simulated user when they start. Useful for logins and
        # other 'do before doing all other things'.
        pass

    def on_stop(self):
        # Methods with the on_stop name will be called for each
        # simulated user when they stop. Useful for logouts and
        # possibly data cleanup.
        pass    

    # TASKS!
    # Methods marked with the `@task` decorator is an action
    # taken by a user This example focuses on changes to a 
    # database, but provides a foundation for creating tests on
    # a more read-focused site

    @task
    def index(self):
        # User goes to the root of the project
        self.client.get('/')

    @task
    def create(self):
        # User posts a create form with the fields 'name'
        # and 'age'
        with self.client.post('/create', dict(name=namer(), age=randint(1,35))) as resp:
            self.pk =  resp.text

    @task
    def update(self):
        # User posts an update form with the fields 'name'
        # and 'age'"
        form_data = dict(id=self.pk, name=namer(), age=randint(1,35))
        self.client.post(f'/{self.pk}/update', form_data)

    @task
    def delete(self):
        # Represents the user getting a random ID and then
        # going to the delete page for it.
        self.client.get(f'/{self.pk}/delete')

class CatsiteUser(HttpUser):
    """
    This class represents simulated users interacting with
    a website.
    """
    # What tasks should be done    
    tasks = [TaskSet]
    # how long between clicks a user should take
    wait_time = between(2, 5)
    # The default host of the target client. This can be changed
    # at any time
    host = 'http://localhost:5001/'    

Sample test site

For reference, this is the test site used to create the above locustfile. I'll admit that the above test is incomplete, a lot more tasks could be added to hit web routes. To use it:

  1. Install FastHTML: pip install python-fasthtml
  2. Copy the file into the directory you want to run it
  3. In that directory, at the command-line, type: python cats.py
  4. Open http://localhost:5001/
# cats.py
from fasthtml.common import *

# Set up the database and table
db = database('cats.db')
class Cat: name:str; age:int; id:int
cats = db.create(Cat, pk='id', transform=True)

# Instantiate FastHTML app and route handler
app, rt = fast_app()

def mk_form(target: str):
    return Form(
            P(A('Home', href=index)),
            Fieldset(
                Input(name='name'),
                Input(name='age', type='number'),

            ),
            Input(type='submit', value='submit'),
            method='post'
        )

def cat_count():
    query = """select count(id) from cat;"""
    result = db.execute(query)
    return result.fetchone()[0]

@rt
def index():
    return Titled('Cats',
        P(A('Create cat', href='/create'), NotStr(' '), A('Random ID', href=random)),
        P(f'Number of cats: {cat_count()}'),        
        Ol(
            *[Li(A(f'{d.name}:{d.age}', href=f'/{d.id}')) for d in cats()]
        )
    )

@rt
def random():
    # Small datasets so we can get away with using the RANDOM() function here
    query = """SELECT id FROM cat ORDER BY RANDOM() LIMIT 1;"""
    result = db.execute(query)
    return result.fetchone()[0]

@rt('/create')
def get():
    return Titled('Create Cat', 
        mk_form('/create')
    )

@rt('/create')
def post(cat: Cat):
    while True:
        try:
            cat = cats.insert(Cat(name=cat.name, age=cat.age))
            break
        except Exception as e:
            print(e)
            raise
    return cat.id

@rt('/{id}')
def cat(id: int):
    cat = cats[id]
    return Titled(cat.name, 
        P(cat.age),
        P(A('update', href=f'/{id}/update')),
        P(A('delete', href=f'/{id}/delete')),
    )


@rt('/{id}/update')
def get(id: int):
    cat = cats[id]
    return Titled('Edit Cat',
        fill_form(mk_form(f'/{cat.id}/update'), cat)
    )

@rt('/{id}/update')
def post(cat: Cat, id: int):
    if id not in cats:
        return RedirectResponse(url=index)
    cat.id = id
    db.begin()
    try:
        cats.update(cat)
        db.commit()        
    except:
        db.rollback()
    return RedirectResponse(url=f'/{cat.id}')

@rt('/{id}/delete')
def cat(id: int):
    if id not in cats:
        RedirectResponse(url=index)
    # db.begin()
    cats.delete(id)
    # db.commit()
    return RedirectResponse(url=index)

serve()

Updates

December 23, 2024 07:03 PM UTC

TIL: Autoreload for Jupyter notebooks

Add these commands to the top of a notebook within a Python cell. Thanks to Jeremy Howard for the tip.

%load_ext autoreload
%autoreload 2

December 23, 2024 07:03 PM UTC

TIL: run vs source

Run

A run launches a child process in a new bash within bash, so variables last only the lifetime of the command. This is why launching Python environments doesn't use run.

./list-things.sh

Source

A source is the current bash, so variables last beyond the running of a script. This is why launching Python environments use source.

source ~/.venv/bin/activate

December 23, 2024 07:03 PM UTC


Juri Pakaste

New Swift Package: tui-fuzzy-finder

Speaking of new Swift libraries, I released another one: tui-fuzzy-finder is a terminal UI library for Swift that provides an incremental search and selection UI that imitates the core functionality of fzf very closely.

I have a ton of scripts that wrap fzf. Some of them try to provide some kind of command line interface with options. Most of them work with pipes where I fetch data from somewhere, parse it with jq, feed it fzf, use the selection again as a part of a parameter for something else, etc. It's all great, except that I really don't love shell scripting.

With tui-fuzzy-finder I want to be able to write tools like that in a language I do actually enjoy a great deal. The package provides both a command line tool and a library, but the purpose of the command line tool is just to allow me to test the library, as writing automatic tests for terminal control is difficult. Competing with fzf in the general purpose CLI tool space is a non-goal.

I haven't implemented the preview features of fzf, nor key binding configuration. I'm not ruling either of those out, but I have not needed them yet and don't plan to work on them before a need arises.

Documentation at Swift Package Index.

December 23, 2024 03:25 PM UTC

New Swift Package: provision-info

I released a new Swift library! provision-info is a Swift package for macOS. Its purpose is to parse and show information about provisioning profile files. There's a command line tool and Swift library. The library part might work on iOS, too, but I have not tried. It relies on Apple's Security framework so no Linux.

It's not actually that new, but it's been sitting in a GitHub repo without any releases or changes for nearly three years. I needed the library in a tool at work a couple of weeks ago, so I added couple of features and finally made the first releases.

The CLI tool allows you to print out the basic metadata fields, the entitlements, the device IDs and the certificates in a profile file. You get them in plain text or as JSON. The library exposes the same data as Swift types.

There's documentation for the Swift APIs at Swift Package Index's excellent documentation hosting service. The command line tool prints out help with --help.

December 23, 2024 03:20 PM UTC


Real Python

How to Remove Items From Lists in Python

Removing items from a Python list is a common task that you can accomplish with various techniques. Whether you need to remove an item by its position or value, Python has you covered. In this tutorial, you’ll explore different approaches to removing items from a list, including using .pop(), the del statement, and .remove().

The .remove() method allows you to delete the first occurrence of a specified value, while .pop() can remove an item by its index and return it. The del statement offers another way to remove items by index, and you can also use it to delete slices of a list. The approach you choose will depend on your specific needs.

By the end of this tutorial, you’ll understand that:

  • To remove an item from a list in Python, you can use various approaches like .pop(), del, .remove(), and .clear().
  • To remove items from a certain position in a list, you use the .pop() method.
  • To delete items and slices from a list in Python, you use the del statement.
  • You use the .remove() method to delete the first occurrence of a specified value from a list.
  • To remove all the items from a list, you use .clear().
  • You can also remove duplicate items using a loop, dictionary, or set.

To get the most out of this tutorial, you should be familiar with basic Python list topics like creating lists, adding items to a list, and accessing items in a list.

Get Your Code: Click here to download the free sample code that you’ll use to remove items from lists in Python.

Take the Quiz: Test your knowledge with our interactive “How to Remove Items From Lists in Python” quiz. You’ll receive a score upon completion to help you track your learning progress:


Interactive Quiz

How to Remove Items From Lists in Python

In this quiz, you'll test your understanding of removing items from lists in Python. This is a fundamental skill in Python programming, and mastering it will enable you to manipulate lists effectively.

How to Remove Specific Items From a List

One common operation you’ll perform on a Python list is to remove specific list items. You may need to remove items based on their position in the list, or their value.

To illustrate how you can accomplish this task, suppose you’re creating a website for a public library. Your web app will allow users to save a list of books they would like to read. It should also allow them to edit and remove books from the list, as well as sort the list.

You can use a Python list to store the user’s reading list as a collection of book titles. For example, the reading list might look something like this:

Python
>>> books = ["Dragonsbane", "The Hobbit", "Wonder", "Jaws"]
Copied!

Now that you have a list of books, you have several ways to remove a single, specific book from the list. One approach is to use the .pop() method.

Removing Items Using the .pop() Method

Sometimes, you may need to remove items at a certain position in a list. For example, in a public library app, users might select books to remove by ticking checkboxes in the user interface. Your app will delete each selected item based on its index, which is the item’s position in the list.

If you know the index of the item you want to remove, then you can use the .pop() method. This method takes the item’s index as an optional argument and then removes and returns the item at that index. If you don’t pass an index argument to the method call, then .pop() will remove and return the last item in the list.

Note that Python lists use zero-based indexing for positioning, which means that the first element in a list is at index 0, the second element is at index 1, and so on. With that in mind, here’s an example of how you can use .pop() to remove and display the first element in your books list:

Python
>>> books.pop(0)
'Dragonsbane'
Copied!

You invoke the .pop() method on the books list with an index of 0, indicating the first element in the list. This call removes the first title, Dragonsbane, from the list and then returns it.

If you check the content of your list after running this code, then you’ll notice that Dragonsbane isn’t there anymore:

Python
>>> books
['The Hobbit', 'Wonder', 'Jaws']
Copied!

Here, you display the book list again after the .pop() call. You can see that your list is now one element shorter because .pop() removed the first title.

As you learned earlier in the tutorial, .pop() removes an item and also returns its value, which you can then use for other operations. For example, suppose the library app also allows users to store a separate list of books they’ve read. Once the user has read a book, they can remove it from the initial book list and transfer the title to the read list:

Python
>>> books = ["Dragonsbane", "The Hobbit", "Wonder", "Jaws"]
>>> read_books = []

>>> read = books.pop(0)
>>> read_books.append(read)

>>> read_books
['Dragonsbane']
>>> books
['The Hobbit', 'Wonder', 'Jaws']
Copied!

On the second line in the example, you create a new, empty list called read_books to store the names of the books the user has read. Next, you use the .pop() method to remove the first title from the original book list and store it in a variable. Then, you use .append() to add the stored title to the read_books list.

Read the full article at https://realpython.com/remove-item-from-list-python/ »


[ Improve Your Python With 🐍 Python Tricks 💌 – Get a short & sweet Python Trick delivered to your inbox every couple of days. >> Click here to learn more and see examples ]

December 23, 2024 02:00 PM UTC


Mike Driscoll

An Intro to pre-commit

You can use many great tools to help you in your software development journey. One such tool is pre-commit, a framework for managing and maintaining multi-language pre-commit hooks. You use pre-commit to run one or more tools before allowing you to commit your code locally. For example, you might run the Flake8 linter or the Ruff formatter on your Python code in GitHub Actions or some other CI. But rather than waiting for CI to run, you want to run those checks locally and automatically.

That is where pre-commit comes in. You tell pre-c0mmit what to run, and it will run right before it allows you to commit your code.If any of those checks fail, you must fix your code before committing it.

Installing pre-commit

pre-commit is a Python package, so you can install it using pip. Here’s the command you’ll need to run in your terminal:

pip install pre-commit

Once pre-commit is installed, you can confirm that it works by running the following:

pre-commit --version

Adding the git Hooks

The next step is to navigate to one of your local GitHub code bases in your terminal. Once inside one of your repos, you will need to run this command:

pre-commit install

This command installs pre-commit in your .git\hooks folder so that pre-commit runs whenever you commit. But how does pre-commit know what to run?

You have to define what pre-commit runs using a special YAML file. You’ll learn how in the next section!

Adding a pre-commit Configuration

You need to add a file named .pre-commit-config.yaml (note the leading period) into the root of your repo. If you want to generate a simple config file, you can run this command:

pre-commit sample-config

Here’s an example config for running Black on your code:

repos:
-   repo: https://github.com/pre-commit/pre-commit-hooks
    rev: v2.3.0
    hooks:
    -   id: check-yaml
    -   id: end-of-file-fixer
    -   id: trailing-whitespace
-   repo: https://github.com/psf/black
    rev: 22.10.0
    hooks:
    -   id: black

Personally, I like to run the Ruff formatter and linter as well as a couple of defaults, so I use this config a lot:

repos:
-   repo: https://github.com/pre-commit/pre-commit-hooks
    rev: v3.2.0
    hooks:
    -   id: trailing-whitespace
    -   id: end-of-file-fixer
    -   id: check-added-large-files

- repo: https://github.com/astral-sh/ruff-pre-commit
  # Ruff version.
  rev: v0.1.7
  hooks:
    # Run the linter.
    - id: ruff
    # Run the formatter.
    - id: ruff-format

When you add a new rule to pre-commit, you should run that rule against all the files in your repo so you don’t have any surprises later on. To do that, you need to run this command:

pre-commit run --all-files

Once you have run all your new rules against all your code files, you can start working on your next feature or bug fix. Then, when you run,  git commit the pre-commit hooks will run, and you’ll see if your code is good enough to pass.

Wrapping Up

There are TONs of hooks you can add to pre-commit. A lot of them are mentioned on the pre-commit website. You can add Mypy, pytest, and much, much more to your pre-commit hooks. Just don’t get too crazy, or they may take too long to run, and you’ll go nuts waiting for it.

Overall, running so many of your CI hooks locally is great because your machine is usually faster than waiting on a queue in CI. Give it a try and see what think!

The post An Intro to pre-commit appeared first on Mouse Vs Python.

December 23, 2024 01:09 PM UTC


Python Bytes

#415 Just put the fries in the bag bro

<strong>Topics covered in this episode:</strong><br> <ul> <li><a href="https://github.com/dbos-inc/dbos-transact-py?featured_on=pythonbytes"><strong>dbos-transact-py</strong></a></li> <li><strong><a href="https://engineering.fb.com/2024/12/09/developer-tools/typed-python-2024-survey-meta/?featured_on=pythonbytes">Typed Python in 2024: Well adopted, yet usability challenges persist</a></strong></li> <li><strong><a href="https://github.com/RightTyper/RightTyper?featured_on=pythonbytes">RightTyper</a></strong></li> <li><strong><a href="https://treyhunner.com/2024/12/lazy-self-installing-python-scripts-with-uv/?featured_on=pythonbytes">Lazy self-installing Python scripts with uv</a></strong></li> <li><strong>Extras</strong></li> <li><strong>Joke</strong></li> </ul><a href='https://www.youtube.com/watch?v=xdR4JFcb01o' style='font-weight: bold;'data-umami-event="Livestream-Past" data-umami-event-episode="415">Watch on YouTube</a><br> <p><strong>About the show</strong></p> <p>Sponsored by us! Support our work through:</p> <ul> <li>Our <a href="https://training.talkpython.fm/?featured_on=pythonbytes"><strong>courses at Talk Python Training</strong></a></li> <li><a href="https://courses.pythontest.com/p/the-complete-pytest-course?featured_on=pythonbytes"><strong>The Complete pytest Course</strong></a></li> <li><a href="https://www.patreon.com/pythonbytes"><strong>Patreon Supporters</strong></a></li> </ul> <p><strong>Connect with the hosts</strong></p> <ul> <li>Michael: <a href="https://fosstodon.org/@mkennedy"><strong>@mkennedy@fosstodon.org</strong></a> <strong>/</strong> <a href="https://bsky.app/profile/mkennedy.codes?featured_on=pythonbytes"><strong>@mkennedy.codes</strong></a> <strong>(bsky)</strong></li> <li>Brian: <a href="https://fosstodon.org/@brianokken"><strong>@brianokken@fosstodon.org</strong></a> <strong>/</strong> <a href="https://bsky.app/profile/brianokken.bsky.social?featured_on=pythonbytes"><strong>@brianokken.bsky.social</strong></a></li> <li>Show: <a href="https://fosstodon.org/@pythonbytes"><strong>@pythonbytes@fosstodon.org</strong></a> <strong>/</strong> <a href="https://bsky.app/profile/pythonbytes.fm"><strong>@pythonbytes.fm</strong></a> <strong>(bsky)</strong></li> </ul> <p>Join us on YouTube at <a href="https://pythonbytes.fm/stream/live"><strong>pythonbytes.fm/live</strong></a> to be part of the audience. Usually <strong>Monday</strong> at 10am PT. Older video versions available there too.</p> <p>Finally, if you want an artisanal, hand-crafted digest of every week of the show notes in email form? Add your name and email to <a href="https://pythonbytes.fm/friends-of-the-show">our friends of the show list</a>, we'll never share it.</p> <p><strong>Michael #1:</strong> <a href="https://github.com/dbos-inc/dbos-transact-py?featured_on=pythonbytes"><strong>dbos-transact-py</strong></a></p> <ul> <li>DBOS Transact is a Python library providing <strong>ultra-lightweight durable execution</strong>.</li> <li>Durable execution means your program is <strong>resilient to any failure</strong>.</li> <li>If it is ever interrupted or crashes, all your workflows will automatically resume from the last completed step.</li> <li>Under the hood, DBOS Transact works by storing your program's execution state (which workflows are currently executing and which steps they've completed) in a Postgres database.</li> <li>Incredibly fast, for example <a href="https://www.dbos.dev/blog/dbos-vs-aws-step-functions-benchmark?featured_on=pythonbytes">25x faster than AWS Step Functions</a>.</li> </ul> <p><strong>Brian #2:</strong> <a href="https://engineering.fb.com/2024/12/09/developer-tools/typed-python-2024-survey-meta/?featured_on=pythonbytes">Typed Python in 2024: Well adopted, yet usability challenges persist</a></p> <ul> <li>Aaron Pollack on Engineering at Meta blog</li> <li>“Overall findings <ul> <li>88% of respondents “Always” or “Often” use Types in their Python code.</li> <li>IDE tooling, documentation, and catching bugs are drivers for the high adoption of types in survey responses,</li> <li>The usability of types and ability to express complex patterns still are challenges that leave some code unchecked.</li> <li>Latency in tooling and lack of types in popular libraries are limiting the effectiveness of type checkers.</li> <li>Inconsistency in type check implementations and poor discoverability of the documentation create friction in onboarding types into a project and seeking help when using the tools. “</li> </ul></li> <li>Notes <ul> <li>Seems to be a different survey than the 2023 (current) dev survey. Diff time frame and results. July 29 - Oct 8, 2024</li> </ul></li> </ul> <p><strong>Michael #3:</strong> <a href="https://github.com/RightTyper/RightTyper?featured_on=pythonbytes">RightTyper</a></p> <ul> <li>A fast and efficient type assistant for Python, including tensor shape inference</li> </ul> <p><strong>Brian #4:</strong> <a href="https://treyhunner.com/2024/12/lazy-self-installing-python-scripts-with-uv/?featured_on=pythonbytes">Lazy self-installing Python scripts with uv</a></p> <ul> <li>Trey Hunner</li> <li>Creating your own ~/bin full of single-file command line scripts is common for *nix folks, still powerful but underutilized on Mac, and trickier but still useful on Windows.</li> <li>Python has been difficult in the past to use for standalone scripts if you need dependencies, but that’s no longer the case with uv.</li> <li>Trey walks through user scripts (*nix and Mac) <ul> <li>Using #! for scripts that don’thave dependencies</li> <li>Using #! with uv run --script and /// script for dependencies</li> <li>Discussion about how uv handles that.</li> </ul></li> </ul> <p><strong>Extras</strong> </p> <p>Brian:</p> <ul> <li><a href="https://courses.pythontest.com?featured_on=pythonbytes">Courses at pythontest.com</a> <ul> <li>If you live in a place (or are in a place in your life) where these prices are too much, let me know. I had a recent request and I really appreciate it.</li> </ul></li> </ul> <p>Michael:</p> <ul> <li><a href="https://bsky.app/profile/hugovk.bsky.social/post/3ldjdh66jy22o?featured_on=pythonbytes">Python 3.14 update</a> released</li> <li><a href="https://talkpython.fm/blog/posts/top-talk-python-podcast-episodes-of-2024/?featured_on=pythonbytes">Top episodes of 2024</a> at Talk Python</li> <li>Universal check for updates macOS: <ul> <li>Settings &gt; Keyboard &gt; Keyboard shortcuts &gt; App shortcuts &gt; +</li> <li>Then add shortcut for single app, ^U and the menu title.</li> <li><img src="https://blobs.pythonbytes.fm/universial-update-check.jpg" alt="" /></li> </ul></li> </ul> <p><strong>Joke:</strong> <a href="https://github.com/shamith09/pygyat?featured_on=pythonbytes">Python with rizz</a></p>

December 23, 2024 08:00 AM UTC


Zato Blog

Using OAuth in API Integrations

Using OAuth in API Integrations

OAuth is often employed in processes requiring permissions to be granted to frontend applications and end users. Yet, what we typically need in API systems integrations is a way to secure connections between the integration middleware and backend systems without a need for any ongoing human interactions.

OAuth can be a good choice for that scenario and this article shows how it can be achieved in Python, with backend systems using REST and HL7 FHIR.

What we would like to have

Let's say we have a typical integration scenario as in the diagram below:

How the validation looks like in practices is something that Zato will not be aware of because it treats the token as an opaque string but, in practice, if the token is self-contained (e.g. JWT data) the system may validate it on its own, and if it is not self-contained, the system may invoke an introspection endpoint on the OAuth server to validate the access token from Zato.

Once the validation succeeds, the backend system will reply with the business data and the interoperability layer will combine the results for the calling application's benefit.

In subsequent requests, the same access token will be reused by Zato with the same flow of messages as previously. However, if the cached token expires, Zato will request a new one from the OAuth server - this will be transparent to the calling application - and the flow will resume.

In OAuth terminology, what is described above has specific names, the overall flow of messages between Zato and the OAuth server is called a "Client Credential Flow" and Zato is then considered a "client" from the OAuth server's perspective.

Configuring OAuth

First, we need to create an OAuth security definition that contains the OAuth server's connection details. In this case, the server is Okta. Note the scopes field - it is a list of permissions ("scopes") that Zato will be able to make use of.

What exactly the list of scopes should look like is something to be coordinated with the people who are responsible for the configuration of the OAuth server. If it is you personally, simply ensure that what is in the the OAuth server and in Zato is in sync.

Calling REST

To invoke REST services, fill out a form as below, pointing the "Security" field to the newly created OAuth definition. This suffices for Zato to understand when and how to obtain new tokens from the underlying OAuth server.

Here is sample code to invoke a backend REST system - note that we merely refer to a connection by its name, without having to think about security at all. It is Zato that knows how to get and use OAuth tokens as required.

# -*- coding: utf-8 -*-

# Zato
from zato.server.service import Service

class GetClientBillingPlan(Service):
    """ Returns a billing plan for the input client.
    """
    def handle(self):

        # In a real service, this would be read from input
        payload = {'client_id': 123}

        # Get a connection to the server ..
        conn = self.out.rest['REST Server'].conn

        # .. invoke it ..
        response = conn.get(self.cid, payload)

        # .. and handle the response here.
        ...

Calling HL7 FHIR

Similarly to REST endpoints, to invoke HL7 FHIR servers, fill out a form as below and let the "Security" field point to the OAuth definition just created. This will suffice for Zato to know when and how to use tokens received from the underlying OAuth server.

Here is sample code to invoke a FHIR server system - as with REST servers above, observe that we only refer to a connection by its name and Zato takes care of OAuth.

# -*- coding: utf-8 -*-

# Zato
from zato.server.service import Service

class GetPractitioner(Service):
    """ Returns a practictioner matching input data.
    """
    def handle(self) -> 'None':

        # Connection to use
        conn_name = 'My EHR'

        # In a real service, this would be read from input
        practitioner_id = 456

        # Get a connection to the server ..
        with self.out.hl7.fhir[conn_name].conn.client() as client:

            # Get a reference to a FHIR resource ..
            practitioners = client.resources('Practitioner')

            # .. look up the practitioner ..
            result = practitioners.search(active=True, _id=practitioner_id).get()

            # .. and handle the response here.
            ...

What about the API clients?

One aspect omitted above are the initial API clients - this is on purpose. How they invoke Zato, using what protocols, with what security mechanisms, and how to build responses based on their input data, this is completely independent of how Zato uses OAuth in its own communication with backend systems.

All of these aspects can and will be independent in practice, e.g. clients will use Basic Auth rather than OAuth. Or perhaps the clients will use AMQP, Odoo, SAP, or IBM MQ, without any HTTP, or maybe there will be no explicit API invocations and what we call "clients" will be actually CSV files in a shared directory that your services will be scheduled to periodically pick up. Yet, once more, regardless of what makes the input data available, the backend OAuth mechanism will work independently of it all.



Next steps

API programming screenshots
➤ Python API integration tutorial
➤ More API programming examples in Python
➤ Visit the support center for more articles and FAQ
Open-source iPaaS in Python

December 23, 2024 08:00 AM UTC

December 22, 2024


Real Python

Strings and Character Data in Python

Python strings are a sequence of characters used for handling textual data. You can create strings in Python using quotation marks or the str() function, which converts objects into strings. Strings in Python are immutable, meaning once you define a string, you can’t change it.

To access specific elements of a string, you use indexing, where indices start at 0 for the first character. You specify an index in square brackets, such as "hello"[0], which gives you "h". For string interpolation you can use curly braces {} in a string.

By the end of this tutorial, you’ll understand that:

  • A Python string is a sequence of characters used for textual data.
  • The str() function converts objects to their string representation.
  • You can use curly braces {} to insert values in a Python string.
  • You access string elements in Python using indexing with square brackets.
  • You can join all elements in a list into a single string using .join().

You’ll explore creating strings with string literals and functions, using operators and built-in functions with strings, indexing and slicing techniques, and methods for string interpolation and formatting. These skills will help you manipulate and format textual data in your Python programs effectively.

To get the most out of this tutorial, you should have a good understanding of core Python concepts, including variables, functions, and operators and expressions.

Get Your Code: Click here to download the free sample code that shows you how to work with strings and character data in Python.

Take the Quiz: Test your knowledge with our interactive “Python Strings and Character Data” quiz. You’ll receive a score upon completion to help you track your learning progress:


Interactive Quiz

Python Strings and Character Data

This quiz will test your understanding of Python's string data type and your knowledge about manipulating textual data with string objects. You'll cover the basics of creating strings using literals and the str() function, applying string methods, using operators and built-in functions, and more!

Getting to Know Strings and Characters in Python

Python provides the built-in string (str) data type to handle textual data. Other programming languages, such as Java, have a character data type for single characters. Python doesn’t have that. Single characters are strings of length one.

In practice, strings are immutable sequences of characters. This means you can’t change a string once you define it. Any operation that modifies a string will create a new string instead of modifying the original one.

A string is also a sequence, which means that the characters in a string have a consecutive order. This feature allows you to access characters using integer indices that start with 0. You’ll learn more about these concepts in the section about indexing strings. For now, you’ll learn about how to create strings in Python.

Creating Strings in Python

There are different ways to create strings in Python. The most common practice is to use string literals. Because strings are everywhere and have many use cases, you’ll find a few different types of string literals. There are standard literals, raw literals, and formatted literals.

Additionally, you can use the built-in str() function to create new strings from other existing objects.

In the following sections, you’ll learn about the multiple ways to create strings in Python and when to use each of them.

Standard String Literals

A standard string literal is just a piece of text or a sequence of characters that you enclose in quotes. To create single-line strings, you can use single ('') and double ("") quotes:

Python
>>> 'A single-line string in single quotes'
'A single-line string in single quotes'

>>> "A single-line string in double quotes"
'A single-line string in double quotes'
Copied!

In the first example, you use single quotes to delimit the string literal. In the second example, you use double quotes.

Note: Python’s standard REPL displays string objects using single quotes even though you create them using double quotes.

You can define empty strings using quotes without placing characters between them:

Python
>>> ""
''

>>> ''
''

>>> len("")
0
Copied!

An empty string doesn’t contain any characters, so when you use the built-in len() function with an empty string as an argument, you get 0 as a result.

To create multiline strings, you can use triple-quoted strings. In this case, you can use either single or double quotes:

Read the full article at https://realpython.com/python-strings/ »


[ Improve Your Python With 🐍 Python Tricks 💌 – Get a short & sweet Python Trick delivered to your inbox every couple of days. >> Click here to learn more and see examples ]

December 22, 2024 02:00 PM UTC

Working With JSON Data in Python

Python’s json module provides you with the tools you need to effectively handle JSON data. You can convert Python data types to a JSON-formatted string with json.dumps() or write them to files using json.dump(). Similarly, you can read JSON data from files with json.load() and parse JSON strings with json.loads().

JSON, or JavaScript Object Notation, is a widely-used text-based format for data interchange. Its syntax resembles Python dictionaries but with some differences, such as using only double quotes for strings and lowercase for Boolean values. With built-in tools for validating syntax and manipulating JSON files, Python makes it straightforward to work with JSON data.

By the end of this tutorial, you’ll understand that:

  • JSON in Python is handled using the standard-library json module, which allows for data interchange between JSON and Python data types.
  • JSON is a good data format to use with Python as it’s human-readable and straightforward to serialize and deserialize, which makes it ideal for use in APIs and data storage.
  • You write JSON with Python using json.dump() to serialize data to a file.
  • You can minify and prettify JSON using Python’s json.tool module.

Since its introduction, JSON has rapidly emerged as the predominant standard for the exchange of information. Whether you want to transfer data with an API or store information in a document database, it’s likely you’ll encounter JSON. Fortunately, Python provides robust tools to facilitate this process and help you manage JSON data efficiently.

While JSON is the most common format for data distribution, it’s not the only option for such tasks. Both XML and YAML serve similar purposes. If you’re interested in how the formats differ, then you can check out the tutorial on how to serialize your data with Python.

Free Bonus: Click here to download the free sample code that shows you how to work with JSON data in Python.

Take the Quiz: Test your knowledge with our interactive “Working With JSON Data in Python” quiz. You’ll receive a score upon completion to help you track your learning progress:


Interactive Quiz

Working With JSON Data in Python

In this quiz, you'll test your understanding of working with JSON in Python. By working through this quiz, you'll revisit key concepts related to JSON data manipulation and handling in Python.

Introducing JSON

The acronym JSON stands for JavaScript Object Notation. As the name suggests, JSON originated from JavaScript. However, JSON has transcended its origins to become language-agnostic and is now recognized as the standard for data interchange.

The popularity of JSON can be attributed to native support by the JavaScript language, resulting in excellent parsing performance in web browsers. On top of that, JSON’s straightforward syntax allows both humans and computers to read and write JSON data effortlessly.

To get a first impression of JSON, have a look at this example code:

JSON hello_world.json
{
  "greeting": "Hello, world!"
}
Copied!

You’ll learn more about the JSON syntax later in this tutorial. For now, recognize that the JSON format is text-based. In other words, you can create JSON files using the code editor of your choice. Once you set the file extension to .json, most code editors display your JSON data with syntax highlighting out of the box:

Editor screenshot with code highlighting for a JSON file

The screenshot above shows how VS Code displays JSON data using the Bearded color theme. You’ll have a closer look at the syntax of the JSON format next!

Examining JSON Syntax

In the previous section, you got a first impression of how JSON data looks. And as a Python developer, the JSON structure probably reminds you of common Python data structures, like a dictionary that contains a string as a key and a value. If you understand the syntax of a dictionary in Python, you already know the general syntax of a JSON object.

Note: Later in this tutorial, you’ll learn that you’re free to use lists and other data types at the top level of a JSON document.

The similarity between Python dictionaries and JSON objects is no surprise. One idea behind establishing JSON as the go-to data interchange format was to make working with JSON as convenient as possible, independently of which programming language you use:

[A collection of key-value pairs and arrays] are universal data structures. Virtually all modern programming languages support them in one form or another. It makes sense that a data format that is interchangeable with programming languages is also based on these structures. (Source)

To explore the JSON syntax further, create a new file named hello_frieda.json and add a more complex JSON structure as the content of the file:

JSON hello_frieda.json
 1{
 2  "name": "Frieda",
 3  "isDog": true,
 4  "hobbies": ["eating", "sleeping", "barking"],
 5  "age": 8,
 6  "address": {
 7    "work": null,
 8    "home": ["Berlin", "Germany"]
 9  },
10  "friends": [
11    {
12      "name": "Philipp",
13      "hobbies": ["eating", "sleeping", "reading"]
14    },
15    {
16      "name": "Mitch",
17      "hobbies": ["running", "snacking"]
18    }
19  ]
20}
Copied!

In the code above, you see data about a dog named Frieda, which is formatted as JSON. The top-level value is a JSON object. Just like Python dictionaries, you wrap JSON objects inside curly braces ({}).

In line 1, you start the JSON object with an opening curly brace ({), and then you close the object at the end of line 20 with a closing curly brace (}).

Read the full article at https://realpython.com/python-json/ »


[ Improve Your Python With 🐍 Python Tricks 💌 – Get a short & sweet Python Trick delivered to your inbox every couple of days. >> Click here to learn more and see examples ]

December 22, 2024 02:00 PM UTC

Using Python's pip to Manage Your Projects' Dependencies

pip is the standard package manager for Python, used to install and manage libraries that aren’t part of the Python standard library. You use pip to manage dependencies and install packages from the Python Package Index (PyPI).

You can verify if you have pip by using commands like where pip3 on Windows or which pip3 on Linux and macOS. To install packages listed in a requirements.txt file, use the command pip install -r requirements.txt. This ensures your environment replicates the specified dependencies, maintaining consistency across different setups.

By the end of this tutorial, you’ll understand that:

  • pip stands for “pip installs packages”, indicating its primary function.
  • pip manages Python packages that aren’t part of the standard library.
  • You should use pip whenever you need external Python packages for your projects.
  • You can install and uninstall packages with pip.
  • You use requirements files to manage projects’ dependencies.

You can do a lot with pip, but the Python community is very active and has created some neat alternatives to pip. You’ll learn about those later in this tutorial.

Get Your Cheat Sheet: Click here to download a free pip cheat sheet that summarizes the most important pip commands.

Take the Quiz: Test your knowledge with our interactive “Using Python's pip to Manage Your Projects' Dependencies” quiz. You’ll receive a score upon completion to help you track your learning progress:


Interactive Quiz

Using Python's pip to Manage Your Projects' Dependencies

In this quiz, you'll test your understanding of Python's standard package manager, pip. You'll revisit the ideas behind pip, important commands, and how to install packages.

Getting Started With pip

So, what exactly does pip do? pip is a package manager for Python. That means it’s a tool that allows you to install and manage libraries and dependencies that aren’t distributed as part of the standard library. The name pip was introduced by Ian Bicking in 2008:

I’ve finished renaming pyinstall to its new name: pip. The name pip is [an] acronym and declaration: pip installs packages. (Source)

Package management is so important that Python’s installers have included pip since versions 3.4 and 2.7.9, for Python 3 and Python 2, respectively. Many Python projects use pip, which makes it an essential tool for every Pythonista.

The concept of a package manager might be familiar to you if you’re coming from another programming language. JavaScript uses npm for package management, Ruby uses gem, and the .NET platform uses NuGet. In Python, pip has become the standard package manager.

Finding pip on Your System

The Python installer gives you the option to install pip when installing Python on your system. In fact, the option to install pip with Python is checked by default, so pip should be ready for you to use after installing Python.

Note: On some Linux (Unix) systems like Ubuntu, pip comes in a separate package called python3-pip, which you need to install with sudo apt install python3-pip. It’s not installed by default with the interpreter.

You can verify that pip is available by looking for the pip3 executable on your system. Select your operating system below and use your platform-specific command accordingly:

Windows PowerShell
PS> where pip3
Copied!

The where command on Windows will show you where you can find the executable of pip3. If Windows can’t find an executable named pip3, then you can also try looking for pip without the three (3) at the end.

Shell
$ which pip3
Copied!

The which command on Linux systems and macOS shows you where the pip3 binary file is located.

On Windows and Unix systems, pip3 may be found in more than one location. This can happen when you have multiple Python versions installed. If you can’t find pip in any location on your system, then you may consider reinstalling pip.

Instead of running your system pip directly, you can also run it as a Python module. In the next section, you’ll learn how.

Running pip as a Module

When you run your system pip directly, the command itself doesn’t reveal which Python version pip belongs to. This unfortunately means that you could use pip to install a package into the site-packages of an old Python version without noticing. To prevent this from happening, you should run pip as a Python module:

Shell
$ python -m pip
Copied!

Notice that you use python -m to run pip. The -m switch tells Python to run a module as an executable of the python interpreter. This way, you can ensure that your system default Python version runs the pip command. If you want to learn more about this way of running pip, then you can read Brett Cannon’s insightful article about the advantages of using python -m pip.

Note: Depending on how you installed Python, your Python executable may have a different name than python. You’ll see python used in this tutorial, but you may have to adapt the commands to use something like py or python3 instead.

Read the full article at https://realpython.com/what-is-pip/ »


[ Improve Your Python With 🐍 Python Tricks 💌 – Get a short & sweet Python Trick delivered to your inbox every couple of days. >> Click here to learn more and see examples ]

December 22, 2024 02:00 PM UTC

How to Flatten a List of Lists in Python

Flattening a list in Python involves converting a nested list structure into a single, one-dimensional list. A common approach to flatten a list of lists is to use a for loop to iterate through each sublist. Then, add each item to a new list with the .extend() method or the augmented concatenation operator (+=). This will “unlist” the list, resulting in a flattened list.

Alternatively, Python’s standard library offers tools like itertools.chain() and functools.reduce() to achieve similar results. You can also use a list comprehension for a concise one-liner solution. Each method has its own performance characteristics, with for loops and list comprehensions generally being more efficient.

By the end of this tutorial, you’ll understand that:

  • Flattening a list involves converting nested lists into a single list.
  • You can use a for loop and .extend() to flatten lists in Python.
  • List comprehensions provide a concise syntax for list transformations.
  • Standard-library functions like itertools.chain() and functools.reduce() can also flatten lists.
  • The .flatten() method in NumPy efficiently flattens arrays for data science tasks.
  • Unlisting a list means to flatten nested lists into one list.

To better illustrate what it means to flatten a list, say that you have the following matrix of numeric values:

Python
>>> matrix = [
...     [9, 3, 8, 3],
...     [4, 5, 2, 8],
...     [6, 4, 3, 1],
...     [1, 0, 4, 5],
... ]
Copied!

The matrix variable holds a Python list that contains four nested lists. Each nested list represents a row in the matrix. The rows store four items or numbers each. Now say that you want to turn this matrix into the following list:

Python
[9, 3, 8, 3, 4, 5, 2, 8, 6, 4, 3, 1, 1, 0, 4, 5]
Copied!

How do you manage to flatten your matrix and get a one-dimensional list like the one above? In this tutorial, you’ll learn how to do that in Python.

Free Bonus: Click here to download the free sample code that showcases and compares several ways to flatten a list of lists in Python.

Take the Quiz: Test your knowledge with our interactive “How to Flatten a List of Lists in Python” quiz. You’ll receive a score upon completion to help you track your learning progress:


Interactive Quiz

How to Flatten a List of Lists in Python

In this quiz, you'll test your understanding of how to flatten a list in Python. Flattening a list involves converting a multidimensional list, such as a matrix, into a one-dimensional list. This is a common operation when working with data stored as nested lists.

How to Flatten a List of Lists With a for Loop

How can you flatten a list of lists in Python? In general, to flatten a list of lists, you can run the following steps either explicitly or implicitly:

  1. Create a new empty list to store the flattened data.
  2. Iterate over each nested list or sublist in the original list.
  3. Add every item from the current sublist to the list of flattened data.
  4. Return the resulting list with the flattened data.

You can follow several paths and use multiple tools to run these steps in Python. Arguably, the most natural and readable way to do this is to use a for loop, which allows you to explicitly iterate over the sublists.

Then you need a way to add items to the new flattened list. For that, you have a couple of valid options. First, you’ll turn to the .extend() method from the list class itself, and then you’ll give the augmented concatenation operator (+=) a go.

To continue with the matrix example, here’s how you would translate these steps into Python code using a for loop and the .extend() method:

Python
>>> def flatten_extend(matrix):
...     flat_list = []
...     for row in matrix:
...         flat_list.extend(row)
...     return flat_list
...
Copied!

Inside flatten_extend(), you first create a new empty list called flat_list. You’ll use this list to store the flattened data when you extract it from matrix. Then you start a loop to iterate over the inner, or nested, lists from matrix. In this example, you use the name row to represent the current nested list.

In every iteration, you use .extend() to add the content of the current sublist to flat_list. This method takes an iterable as an argument and appends its items to the end of the target list.

Now go ahead and run the following code to check that your function does the job:

Python
>>> flatten_extend(matrix)
[9, 3, 8, 3, 4, 5, 2, 8, 6, 4, 3, 1, 1, 0, 4, 5]
Copied!

That’s neat! You’ve flattened your first list of lists. As a result, you have a one-dimensional list containing all the numeric values from matrix.

With .extend(), you’ve come up with a Pythonic and readable way to flatten your lists. You can get the same result using the augmented concatenation operator (+=) on your flat_list object. However, this alternative approach may not be as readable:

Python
>>> def flatten_concatenation(matrix):
...     flat_list = []
...     for row in matrix:
...         flat_list += row
...     return flat_list
...
Copied!

Read the full article at https://realpython.com/python-flatten-list/ »


[ Improve Your Python With 🐍 Python Tricks 💌 – Get a short & sweet Python Trick delivered to your inbox every couple of days. >> Click here to learn more and see examples ]

December 22, 2024 02:00 PM UTC


Michael Foord

New Article: Essential Python Web Security Part 1

Security

The Open Source Initiative have published part one of an article of mine. The article is called “Essential Python Web Security” and it’s part one of a series called “The Absolute Minimum Every Python Web Application Developer Must Know About Security”. The subject is Full Stack Security for Python web applications, based on the Defence in Depth approach.

This series explores the critical security principles every Python web developer should know. Whilst hard and fast rules, like avoiding plaintext passwords and custom security algorithms, are essential - a deeper understanding of broader security principles is equally important. This first pots delves into fundamental security best practises, ranging from general principles to specific Python-related techniques.

Part 2, on Cryptographic Algorithms, will be published soon. When the series is complete it will probably also be available as an ebook. The full document, about fifty pages, can be read here:

Special thanks to Gigaclear Ltd who sponsored the creation of this article. Also thanks to Dr David Mertz and Daniel Roy Greenfeld for technical reviews of this article prior to publication.

December 22, 2024 12:00 AM UTC

December 21, 2024


Dan Yeaw

A Big Job Change

I recently changed jobs, and now I am an Engineering Manager for OSS at Anaconda!

Anaconda Logo

This is my second major career pivot, and I thought I would share why I decided to make the change. Even though being a Submarine Officer, a Functional Safety Lead, and working on OSS are very different, they share a common thread of leadership and deeply technical engineering. I’m excited to bring these skills into my new role.

Goodbye to Ford

I spent the last 11 years leading Functional Safety at Ford. It was incredibly rewarding to grow from an individual contributor to a manager and eventually to leading a global team dedicated to ensuring Ford vehicles were safe.

While this role let me support Functional Safety Engineers across the company, I started to miss getting hands-on with technical contributions since most of my time was focused on leading the team.

Looking back, there are a couple of things I wish had been different at Ford:

  1. A strong bias for external talent with executive leadership
  2. Too much bureaucracy, especially in approval processes

Having a good mix of new talent join an organization is so important because fresh ideas and perspectives can make a big difference. However, in Ford’s software engineering areas, about 90% of the executive leadership roles were filled by people from outside the company. While I wasn’t aiming for higher leadership roles, this clear preference for external hires made it feel like developing and retaining internal talent wasn’t a priority. As you might expect, it took new leaders a while to adapt, and there was a lot of turnover.

On top of that, the approval process for things like hiring and travel was overly complicated. Simple approvals could take months with no feedback. This culture of control slowed everything down. Delegating authority—like giving managers a budget and headcount to work with and holding them accountable—would have made things so much smoother and faster.

The thing I’ll miss most about Ford is the people. I loved collaborating with all the Functional Safety Engineers and everyone else I worked with. I wish them all the best in the future!

Hello Anaconda

I am now an Engineering Manager for Open Source Software at Anaconda, where I lead a team of engineers working on amazing projects like:

...and more!

Over the last seven years, I’ve been contributing to open source projects, especially in Python. Getting the chance to lead a team that does this full-time feels like a dream come true.

One of the things I’m most excited about with these projects is how they help make programming more accessible. BeeWare, for example, makes it possible to create apps for mobile and desktop, and PyScript lets you write Python directly in your web browser. Both tools are fantastic for helping anyone pick up Python, build something useful, and share it with others. Meanwhile, Jupyter and fsspec are key tools for data science, making it easier to analyze diverse datasets and integrate different data sources.

I’m thrilled to have the opportunity to strengthen the open-source communities around these projects, encourage healthier collaboration, and create more value for Python users by connecting these tools with the broader PyData ecosystem.

December 21, 2024 08:05 PM UTC


Real Python

Basic Data Types in Python: A Quick Exploration

Python data types are fundamental to the language, enabling you to represent various kinds of data. You use basic data types like int, float, and complex for numbers, str for text, bytes and bytearray for binary data, and bool for Boolean values. These data types form the core of most Python programs, allowing you to handle numeric, textual, and logical data efficiently.

Understanding Python data types involves recognizing their roles and how to work with them. You can create and manipulate these data types using built-in functions and methods. You can also convert between them when necessary. This versatility helps you manage data effectively in your Python projects.

By the end of this tutorial, you’ll understand that:

  • Python’s basic data types include int, float, complex, str, bytes, bytearray, and bool.
  • You can check a variable’s type using the type() function in Python.
  • You can convert data types in Python using functions like int(), float(), str(), and others.
  • Despite being dynamically typed, Python does have data types.
  • The most essential data types in Python can be categorized as numeric, sequence, binary, and Boolean.

In this tutorial, you’ll learn only the basics of each data type. To learn more about a specific data type, you’ll find useful resources in the corresponding section.

Get Your Code: Click here to download the free sample code that you’ll use to learn about basic data types in Python.

Take the Quiz: Test your knowledge with our interactive “Basic Data Types in Python: A Quick Exploration” quiz. You’ll receive a score upon completion to help you track your learning progress:


Interactive Quiz

Basic Data Types in Python: A Quick Exploration

Take this quiz to test your understanding of the basic data types that are built into Python, like numbers, strings, bytes, and Booleans.

Python’s Basic Data Types

Python has several built-in data types that you can use out of the box because they’re built into the language. From all the built-in types available, you’ll find that a few of them represent basic objects, such as numbers, strings and characters, bytes, and Boolean values.

Note that the term basic refers to objects that can represent data you typically find in real life, such as numbers and text. It doesn’t include composite data types, such as lists, tuples, dictionaries, and others.

In Python, the built-in data types that you can consider basic are the following:

Class Basic Type
int Integer numbers
float Floating-point numbers
complex Complex numbers
str Strings and characters
bytes, bytearray Bytes
bool Boolean values

In the following sections, you’ll learn the basics of how to create, use, and work with all of these built-in data types in Python.

Integer Numbers

Integer numbers are whole numbers with no decimal places. They can be positive or negative numbers. For example, 0, 1, 2, 3, -1, -2, and -3 are all integers. Usually, you’ll use positive integer numbers to count things.

In Python, the integer data type is represented by the int class:

Python
>>> type(42)
<class 'int'>
Copied!

In the following sections, you’ll learn the basics of how to create and work with integer numbers in Python.

Integer Literals

When you need to use integer numbers in your code, you’ll often use integer literals directly. Literals are constant values of built-in types spelled out literally, such as integers. Python provides a few different ways to create integer literals. The most common way is to use base-ten literals that look the same as integers look in math:

Python
>>> 42
42

>>> -84
-84

>>> 0
0
Copied!

Here, you have three integer numbers: a positive one, a negative one, and zero. Note that to create negative integers, you need to prepend the minus sign (-) to the number.

Python has no limit to how long an integer value can be. The only constraint is the amount of memory your system has. Beyond that, an integer can be as long as you need:

Python
>>> 123123123123123123123123123123123123123123123123 + 1
123123123123123123123123123123123123123123123124
Copied!

For a really, really long integer, you can get a ValueError when converting it to a string:

Read the full article at https://realpython.com/python-data-types/ »


[ Improve Your Python With 🐍 Python Tricks 💌 – Get a short & sweet Python Trick delivered to your inbox every couple of days. >> Click here to learn more and see examples ]

December 21, 2024 02:00 PM UTC