See the question and my original answer on StackOverflow

Here is some sample code that's using the IPropertyStore interface through propsys:

import pythoncom
from win32com.propsys import propsys
from win32com.shell import shellcon

# get PROPERTYKEY for "System.Keywords"
pk = propsys.PSGetPropertyKeyFromName("System.Keywords")

# get property store for a given shell item (here a file)
ps = propsys.SHGetPropertyStoreFromParsingName("c:\\path\\myfile.jpg", None, shellcon.GPS_READWRITE, propsys.IID_IPropertyStore)

# read & print existing (or not) property value, System.Keywords type is an array of string
keywords = ps.GetValue(pk).GetValue()
print(keywords)

# build an array of string type PROPVARIANT
newValue = propsys.PROPVARIANTType(["hello", "world"], pythoncom.VT_VECTOR | pythoncom.VT_BSTR)

# write property
ps.SetValue(pk, newValue)
ps.Commit()

This code is pretty generic for any Windows property.

I'm using System.Keywords because that's what corresponds to jpeg's "tags" property that you see in the property sheet.

And the code works for jpeg and other formats for reading (GetValue) properties, but not all Windows codecs support property writing (SetValue), to it doesn't work for writing extended properties back to a .png for example.