After spending most of the day on this, I think I figured it out. You have to return the device to idle before you can retrieve the data. The READ command is supposed to be a FETCH and delete but I haven't been able to get that to work. The workaround I'm using is to query the amount of data points in memory and then remove that data in a separate transaction. Feels cludgey but it works.
import pyvisa as visa
import time
import csv
import datetime
# Setup our instrument
rm = visa.ResourceManager()
v34465A = rm.open_resource('USB0::0x2A8D::0x0101::MY57514376::0::INSTR') # Open instrument over USB
v34465A.write(':CONFigure:VOLTage:DC %G,%s' % (1.0, 'MAXimum')) # Set range and resolution
v34465A.write(':SAMPle:COUNt %d' % (1)) # Specify number of samples to 100
v34465A.write(':SAMPle:SOURce %s' % ('IMMediate')) # Sample as fast as possible
v34465A.write(':TRIGger:SOURce %s;SLOP POS' % ('EXTernal')) # External triggering
v34465A.write(':TRIGger:COUNt %s' % ('INFinity')) # Trigger as many times as memory allows
v34465A.write(':FORMat:DATA %s' % ('ASCii')) # Data format must be set to fetch
v34465A.write(':INITiate:IMMediate') # Start sampling
# Wait for keypress for testing purposes
print("Sampling...")
input("Press Enter to continue...")
print("Done")
# ABORT returns the DMM to idle state to retrieve data
v34465A.write(':ABORt')
# Retrieve the data from the instrument by reading how much data there is, and removing that amount of data
temp_values = v34465A.query_ascii_values(':DATA:POINts?')
points = int(temp_values[0])
temp_values = v34465A.query_ascii_values(':DATA:REMove? %d' % (points))
# Create data file
fileNameString = datetime.datetime.now().strftime("%y%m%d%H%M") + "_data.csv"
f1 = open(fileNameString, "w", newline='', encoding='utf-8')
c = csv.writer(f1)
header = ['Sample', 'Voltage']
c.writerow(header)
sample_counter = 0
for x in temp_values:
data = [ sample_counter, x ]
c.writerow(data)
sample_counter = sample_counter+1
f1.close()
v34465A.close()
rm.close()