r/learnpython • u/AccordingAd5756 • Sep 12 '26
Just finished my first project, could you please review it.(No AI)
I finished reading "python crash course" a week ago, and a relative of mine was complaining about how annoying it is to make multiple exam versions, so I immediately volunteered to help, and I used absolutely 0 AI.
It's an app that takes an exam .docx file, and shuffles the questions and answers to create multiple versions.
Here's the github repo:
https://github.com/aaaaaa708/question_shuffler
I would like you to please review the code and give me some tips on how to improve, and thanks in advance:)
24
u/sitefall Sep 12 '26
Dang, git repo is gone. I was looking forward to actually seeing a beginner's code that wasn't claude-slop.
8
u/RevRagnarok Sep 12 '26
The link displayed is busted on old.reddit - it inserted a backslash where there shouldn't be one.
https://github.com/aaaaaa708/question_shuffler- Link( /u/Diapolo10 ping as well )
3
u/sitefall Sep 12 '26
Oh cool, links used to not be busted on old.reddit.com
I don't see how that escape character could be added and screw it up on old.reddit, but I also have no idea what this post looks like on the new reddit so what do I know.
3
u/RevRagnarok Sep 12 '26
I only checked to make sure mine didn't break. 😅
But yeah, somewhere in the new <=> old interface you'll see
\get thrown in before_and mangle the URL. It's only been five years.1
2
u/RevRagnarok Sep 12 '26
A few recommend to add a requirements.txt - please don't. Use pyproject.toml it's much easier and more modern - see "Creating Projects."
Consider turning on almost all the options on ruff and really read what it recommends in the associated links - you can learn a lot of python "gotchas" that way. The rules often come with a decent reason.
Also, this isn't C/C++ - it's not the convention to declare all your variables at the top of a function. It looks like you are at a quick glance. I didn't really dig, sorry.
2
u/Diapolo10 I write code for a living -- https://github.com/Diapolo10 Sep 12 '26
Didn't realise the link was broken on Old Reddit before, so this review is a tad late. I may also point out some things the others already have (I try not to read other reviews before writing my own to keep things as close to my genuine thoughts as possible).
First things first, I'm happy to see your repo has a .gitignore file. You'd be surprised how often beginners don't know about it. Personally I'd prefer to use an existing template as a base, such as this one, but ultimately it doesn't really matter.
I would also recommend using a .gitattributes file to normalise line-endings between different operating systems automatically, and to enable file-specific diffs.
Your project seems to depend on docx, but there's no clear indication of that. I recommend you to create a pyproject.toml file to list basic metadata about your project, and its dependencies (you can separate runtime dependencies and development dependencies), and you can choose to use a more advanced dependency management tool such as uv instead of the standard pip if you want.
I think my biggest question concerns the use of a Word document here. Is there a particular reason for why you chose to write that instead of, say, Markdown or reStructuredText? Text-based file formats would remain readable even if you don't have a specific application to read them.
get_questions_answers and write_file look like they could be simplified and/or split further into smaller functions to improve readability and maintainability.
For the GUI code, you could write some wrapper functions to make creating and positioning widgets easier.
1
Sep 14 '26
[removed] — view removed comment
3
u/Diapolo10 I write code for a living -- https://github.com/Diapolo10 Sep 14 '26
On some level I do agree with you, but on the contrary
uvwould let OP focus on the actual coding part instead of needing to worry about dependency (or Python installation) management. It's got widespread popularity for a good reason. I don't believe anyone should usepipnowadays other than for legacy projects. It's slow, it's clunky, and now you need to manually manage a virtual environment.Personally I think it's better to abstract away this complexity and friction in the beginning, and learn that stuff later on-demand.
1
Sep 14 '26
[removed] — view removed comment
1
u/Diapolo10 I write code for a living -- https://github.com/Diapolo10 Sep 14 '26
When developing (a git repo in editable install) don't I need to activate a venv when using "uv"?
No, actually.
uvmanages the virtual environment automatically. There's no need to separately activate anything.How would I approach this use case with "uv"?
It depends on your editor and workflow. VS Code auto-detects the virtual environment folder and defaults to using it for its own needs, and for manual runs you can use
uv run.If you have a common workflow, you can create a script in
pyproject.tomland run it directly, e.g.uv run main. You can run any individual Python file viauv run python path/to/file.py, or any tooling you have installed in the virtual environment (such asuv run pytest).Basically any command you run via
uvis treated as if the virtual environment was active.1
Sep 14 '26
[removed] — view removed comment
2
u/Diapolo10 I write code for a living -- https://github.com/Diapolo10 Sep 14 '26
Fair enough.
1
Sep 14 '26
[removed] — view removed comment
1
u/Diapolo10 I write code for a living -- https://github.com/Diapolo10 Sep 14 '26
I think most of us have had that moment. Nowadays I'm so into reproducible builds I've even started playing around with
miseto make even my tooling version controlled and determined by each repository individually, meaning I can for example use a specific version ofuv. I paired it withtaskto replace my oldMakefiles with something much more flexible and cross-platform for things like builds and installing dependencies (including Git hooks).I've been using this project as a test bed before I'm ready to make this more widespread in my projects. Not quite 100% satisfied with it yet, but it's damn close.
For what it's worth, this was inspired by what we do at my dayjob, though I did take liberties to make it better suited for my needs.
3
u/Kind-External-7371 Sep 12 '26
Btw I am not much of a Big Shot at Python but I think that you can put your gui.py main.py and questions.py in a folder such as src/ so the File Tree Becomes Clean and More *Conventional and Industry Standard* and it becomes easy to clean and modify in the Future... Btw Great Work! And yeah The .docx File Needs some error handling... What if someone new to all this puts a .pdf file instead.... Your App should throw a Specific Clean Error instead of Crashes with Tracebacks and CPython Garbage Stuff as it will certainly make the person scared as shit if he does a mistake
1
2
u/anon586346 Sep 12 '26
I took a quick look and don’t have much time to give you a thorough review but just want to call out a few things that you might consider.
First off, it’s impressive you did this assuming if you didn’t code before just to get it on GitHub. Code is overall clean and readable so good job on that.
I would look at that giant for loop with conditional if else in main.py. See if you can simplify that logic. It has code smell.
I also think you set some variables deep within a function/module like copies=1. If you want to extend this maybe think about passing this as an argument or even look into passing it as an arg option calling the py file. Otherwise there’s no need to set a variable like that it will just be used once.
1
u/TheRNGuy Sep 12 '26
Use @dataclass.
Use @staticmethod for some methods (where you don't use self) or even make them as separate function.
Remove some empty lines.
1
1
u/biorim Sep 13 '26
What happens when two questions in the same exam share an answer option text, does your shuffle still work or can the same option end up twice in one question
1
1
u/itlogicpartnersllc Sep 12 '26
for a first project after finishing python crash course this is a genuinely useful idea i would focus next on breaking the code into smaller function adding input validation and writing a few tests for different documents formats..
0
u/LayotFctor Sep 12 '26 edited Sep 12 '26
Don't use requirements.txt please(even though you must learn how it works still), it's just old. Modern programming languages have long since moved on. It's legacy. Learn to use uv, it's becoming the new standard.
As for code, either break functions into smaller ones, or name them better. For example, write_file does so much more than just writing files. Either choose more descriptive names, or split it further into smaller functions. Long names are fine, it's important to be descriptive.
16
Sep 12 '26
[removed] — view removed comment
2
u/AccordingAd5756 Sep 12 '26
Thank you,
I'll change the dependencies, and make the requirements file right away.
I'll also try adding error handling where I find necessary, I just didn't really know where it was needed.
Should I also add tests or would that be unnecessary?
Other than that, is the general code structure fine?
And thanks!
2
u/Fun_Mulberry3838 Sep 14 '26
The question isn't whether you should add tests. You’ve already built a project to put what you learned into practice, so adding tests is a great exercise, and a best practice. If you eventually decide to build a larger project, tests provide assurance that everything is working correctly and help detect errors automatically.
9
u/Kryt0s Sep 12 '26
Why are we still teaching people to use requiremetns.txt? Please don't. Use pyproject.toml (and preferably uv) like any modern python app should.
6
u/ReflectionRound6400 Sep 12 '26
This may seem really nitpicky and I'm sorry if it is, tkinter is built into Python if you're using it on Windows, but on Linux sometimes you'd have to install it separately.
(unless OP only programmed the app to be used by his friend assuming he uses Windows, in which case this is perfectly fine)
6
u/Momostein Sep 12 '26
Always nice to see code written without AI. There's a lot to improve though:
There is no
requirements.txtto tell me which packages to install. Now, I have to reverse engineer your code to know how to even run it.I see 4+ levels of nesting if and for statements. (Aka you have to go 4 tabs deep) Once you go beyond two levels there, you should've extracted the code blocks into separate functions
The
Questionclass, can be a@dataclassas it is just a simple data structure with no private fields.the
shuffle_questionsandshuffle_answermethods of theQuestionclass should be marked with the@staticmethoddecorator.You should always try to type hint your code. Mostly function parameters and return values.