Iterate over a list of list names as file names
As you already noticed you have repeated code. you have variable names for your lists and also string definitions for list names which most probably should match. while this is no big problem for just 3 lists it could get cumbersome on adding another list. A simple way to avoid such name-to-string matching edits is to hold such variables in a dict() and have the string definition only.

The second problem is to have different iterables which must match in length and order to be zipped lateron. Avoid this by holding tuples (or other containers) in a single iterable from the beginning. key-value pairs in a dict() also provide this binding.

I your case I'd recommend to use the strings as keys 

#avoid named variables
lists = {name:[] for name in ('singles', 'multiples' , 'zeros')}

#access lists via name
lists['singles'].append(0)

#access via temporary
l = lists['singles']
l.append[0]

#iterate for saving
for s, l in lists.items():
    writelist(list=l, fname=s + '.csv') 




EDIT:

Above answer applies to the first version of code where all that list init was skipped. While all still valid this can now be applied to the real code. concise and following the KISS principle. Names could be improved but are left here for outlining changes only.

lists = {name:[] for name in ('singles', 'multiples' , 'zeros')}

for row in df.itertuples():
    query = best_q(row)
    hits, uri = ask_rkd(query)
    if hits == 0:
        query = bracket_q(row)
        hits, uri = ask_rkd(query)

    if hits == 1: 
        lists['singles'].append([row.priref, row.name, hits, uri])
    elif hits &gt; 1:
        lists['multiples'].append([row.priref, row.name, hits])
    elif hits == 0:
        lists['zeroes'].append([row.priref, str(row.name)])  # PM: str!! 

for s, l in lists.items():
    listfile = '{}_{}.csv'.format(input_fname, s)
    writelist(list=l, fname=listfile) 

outfile = fname + '_out' + ext
df.to_csv(outfile, sep='|', encoding='utf-8-sig')