The only goal came on 12 minutes when Niclas Eliasson's cross from the right found the big striker unmarked to head home from eight yards.
Victory extended City's unbeaten run to 10 games, but they were pushed all the way by a Reading side unlucky not to take a point on the balance of play.
But Reading responded well to falling behind. In the 20th minute the impressive Ovie Ejaria had a shot blocked and fired just wide from the rebound.
Buoyed by his goal, Diedhiou had a shot deflected for a corner, but Reading were looking equally dangerous and Ejaria shot over from the edge of the box.
City had two chances at the start of the second half, O'Dowda forcing a save from Rafael Cabral with a low drive and an Eliasson cross fizzing through the six-yard box with no team-mate able to get a touch.
Reading should have equalised on 56 minutes when Ejaria burst into the penalty area on the left and produced a perfect low cross only for Puscas to get his feet mixed up at the far post and fail to convert from six yards.
Six minutes later Puscas was replaced by Lucas Boye, with Reading on top and Ejaria causing City countless problems. A mazy run to the byline saw him send in another low cross, which was desperately cleared.
A misplaced pass by Semenyo saw Reading break in the 79th minute and Meite's strong run ended with a shot that flashed wide. Visiting boss Jose Gomes then sacrificed one of his three centre-backs as Michael Morrison was replaced by Lucas Joao.
A long throw from the left almost brought an equaliser as City defender Ashley Williams poked the ball just wide of his own net. Then Bentley's failure to claim a cross led to a goalmouth scramble from which City just about escaped.
In a frantic finish, Bentley saved brilliantly from Boye's low shot and City's third substitute Kasey Palmer finished weakly when he should have scored.