Generating PNG barcodes from a CSV I wrote the following code to generate a series of barcodes given a CSV with a list of ISBNs in the first column and titles in the second, using the python-barcode library (which itself requires pillow to generate PNGs and JPGs). I am fairly new with Python and have had little formal training, and so would be interested in any and all feedback regarding functionality, formatting, and anything else I might be missing.

import os
import csv
import barcode
from barcode.writer import ImageWriter

def create_code_png(isbn,title):
    """Creates barcode, gives ISBN and title"""
    isbn13 = barcode.get_barcode_class('ean13')
    return isbn13(isbn, writer = ImageWriter())

def remove_forbidden(string_in):
    """Removes characters forbidden from windows file names from a string"""
    forbidden_chars = ":;&lt;&gt;\"\\/?*|."
    return "".join([char for char in string_in if char not in forbidden_chars])

def codes_from_csv(list_location,destination_folder):
    """Creates PNG Barcodes from a csv, placing them in a given folder"""
    with open(list_location, newline='') as csvfile:
        os.chdir(destination_folder)
        for row in csv.reader(csvfile, dialect='excel'):
            code = create_code_png(isbn:=row[0],title:=remove_forbidden(row[1]))
            code.save(isbn + " " + title)

if __name__ == "__main__":
    codes_from_csv("P:\\barcodes.csv","E:\\Barcodes")
Since I think this is worth more than just a comment on another answer, in your codes_from_csv you are (ab)using the new walrus operator. Assignment expressions are not the right thing to do here. What they do is assign local variables (outside of the function!), and then the values of those local variables (but not their names) are passed by position to the function.

A small example of how this can lead to unexpected results:

def f(a, b):
    return a // b

# Normal positional arguments, order matters
f(3, 1)
# 3
f(1, 3)
# 0

# Keyword arguments, order does not matter, only name
f(a=3, b=1)
# 3
f(b=1, a=3)
# 3

# Using the walrus operator, variables are assigned,
# but are passed as positional arguments.
# The names of the (external) variables do not matter to the function!
f(a:=3, b:=1)
# 3
f(b:=1, a:=3)
# 0


In other words the last example is equivalent to:

b = 1
a = 3
f(b, a)
# 0


This might be what you want, but since you are using the names of the arguments of the function, it probably isn't. In your code it just so happens to work because you use the same order as in the function definition. This might be a source of bugs at some future point, which could be very hard to find!