So I am trying to perform a frequency shift on a set of real valued points.  In order to achieve a frequency shift, one has to multiply the data by a complex exponential, making the resulting data complex. If I multiply by just a cosine I get results at both the sum and difference frequencies. I want just the sum or the difference. 
What I have done is multiply the data by a complex exponential, use fft.fft() to compute the fft, then used fft.irfft() on only the positive frequencies to obtain a real valued dataset that has only a sum or difference shift in frequency. This seems to work great, but I want to know if there are any cons to doing this, or maybe a more appropriate way of accomplishing the same goal. Thanks in advance for any help you can provide!
What you are doing is perfectly fine.  You are generating the analytic signal to accommodate the negative frequencies in the same way a discrete Hilbert transform would.  You will have some scaling issues - you need to double all the non-DC and non-Nyquist signals in the real frequency portion of the FFT results.
Some practical concerns are that this method imparts a delay of the window size, so if you are trying to do this in real-time you should probably examine using a FIR Hilbert transformer and the appropriate sums.  The delay will be the group delay of the Hilbert transformer in that case.
Another item of concern is that you need to remember that the DC component of your signal will also shift along with all the other frequencies.  As such I would recommend that you demean the data (save the value) before shifting, zero out the DC bin after you FFT the data (to remove whatever frequency component ended up in the DC bin), then add the mean back to preserve the signal levels at the end.
In python, If I perform an fft on complex data, then irfft only the positive frequencies, how does that affect the data?