Lightweight Tic-Tac-Toe in Python
The logic behind this section seems to be a little off.

for p, s in self.ploys.items():
    for i in [i for i,n in enumerate(s) if umove in n]:
        del self.ploys[p][i]


When you delete the value at self.ploys[p][i] this essentially means that:

self.ploys[p][i + 1] is now at position self.ploys[p][i]
self.ploys[p][i + 2] is now at position self.ploys[p][i + 1]
etc 


Because the comprehension in the second line finds the indices to the original array, all the proceeding deletes will delete the element 1 index ahead of their target, the next delete will be 2 ahead, and so on.

To fix this you can just iterate through the loop backwards.

for p, s in self.ploys.items():
    for i in [i for i,n in enumerate(s) if umove in n][::-1]:
        del self.ploys[p][i]


Along with that, I think it would help readability to give variables in your loop meaningful names.

It's much less cryptic as:

for ploy_index, soln_list in self.ploys.items():
    for soln_index in [i for i, soln in enumerate(soln_list)
                      if umove in soln][::-1]:
        del self.ploys[ploy_index][soln_index]




I notice is that in PlayUser you write the following.

while umove not in grid or (umove in self.umoves or
    umove in self.cmoves):
    ...


These brackets are a little confusing. When line length is a concern, you should put the entire expression in brackets or use the \ continuation. And although not explicitly in PEP8, I think it also looks better to add extra indentation to easily identify the condition from the logic.

while (umove not in grid or 
       umove in self.umoves or
       umove in self.cmoves):
    ...