It makes no difference whether you know Python or not to use Trac just like it makes no difference whether you know PHP or not to use Wikipedia.
The biggest gap of Trac's implementation is one that only a project participant on multiple projects would see, namely that each project must be in a separate Trac instance. That means you would have no unified view of all issues from all projects. For us, that hasn't been a show-stopper.
We have modified Trac's workflow to model our actual workflow. Our clients get accounts on Trac and we use the ticketing system as a "ball in court" system where we bounce issues back and forth between our team and the client's team until we arrive at resolution.
For example, a client might open a ticket that describes some feature request. Invariably, the client will be looking for an estimate of effort on that feature. By default, all new tickets are assigned to the PM. The PM gets notified by email with a summary of the ticket, logs into Trac, and accepts the ticket. Optionally, he might accept the ticket and assign the ticket. The assigned party might not have information in the ticket to provide an estimate of effort. There might be other critical pieces of information missing so that person will ask questions of the client, set the ticket to "need_info" state and sets the owner of the ticket to the client.
At every state change, Trac will notify the reporter, the owner, and by default, the PM so everyone who needs to know is kept informed. Additionally, we have the option of cc:ing others on the ticket, which we sometimes do as necessary.
The client answers the questions, sets the ticket to "info_provided" state and sets the owner back to the party who had bounced it over them. Assuming we don't have to do another round of Q&A, the owner will comment on the ticket and estimate the effort, set the ticket to "needs_approval" and set the owner to the client.
If the client has enough information to make a decision and they want us to implement this new feature, they set the ticket to "approved" and bounce it back to us. If they don't want to proceed, they can close the ticket.
If we're ready to start working on that ticket, the team member who will be implementing the feature will set the ticket to "work_in_progress". That gives the client an indication that this issue didn't just disappear into a black hole.
When the developer has finished, he'll set the ticket to "ready_for_qa" and set the owner to someone on our QA team. The QA person can either bounce it back to the developer as "needs_work" with comments or bounce it over to the client as "ready_for_user_acceptance". Again, the client can bounce it back as "needs_work" and explain why or they can accept by closing the ticket.
We use Trac's milestones roughly as SCRUM cycles. We split each month into the first half and second half so we have two cycles per month. We two special milestones: "Not Scheduled" and "Special Projects". I wanted to explicitly see "Not Scheduled" to emphasize the fact that the ticket is in the backlog so we created "Not Scheduled". "Special Projects" are bigger projects for which we don't have funding yet but we'll eventually get to once we do.
Trac's excellent reporting makes it easy for project participants to know who is responsible for what at any given time and gives everyone an idea of the progress (or lack thereof) in the project.
Trac's wiki is quite good. we use it for project documentation. The wiki syntax is quite simple and can be used everywhere. We have Trac integrated with Subversion and Mercurial so we can reference the changeset in the ticket and in the commit log, reference the ticket in order to have that audit trail.
We use PostgreSQL behind Trac so the occasional time we have to do mass changes on tickets, such moving a bunch of tickets from one milestone to another, it's very easy to do it in the back-end. The data model isn't very complicated so it's easy to figure it out.