#π I started Python back in April, I've done my best to make this as minimal and simple as possible.
109 messages Β· Page 1 of 1 (latest)
@old iris
Remember to:
- Ask your Python question, not if you can ask or if there's an expert who can help.
- Show a code sample as text (rather than a screenshot) and the error message, if you've got one.
- Explain what you expect to happen and what actually happens.
:warning: Do not pip install anything that isn't related to your question, especially if asked to over DMs.
(Reposted as it was shut and nobody responded)
on first glance it looks fine
curious why you decided to alias Path as P and send2trash as recycle
i would split launch_program() into launch_client() and launch_server() as the logic is technically entirely separate
the type in def delete_old_dll(type): doesn't really describe much (and actually overwrites a builtin). i would rename it to something like move_after_deletion and replace if type == 1: with if move_after_deletion:
ClientStr and ServerStr don't look like they're used anywhere
shutil.copy(NewDLL, ServerPath / OldDLLName) can be replaced with shutil.copy(NewDLL, OldDLL) since they refer to the same path anyways
Just to make it look more clean
Would that matter if type never gets used
Ah yeah forgot to delete that, it was used at one point
honestly not really just a nitpick
Ah I didn't know that, thanks
confused by this tho
since
def launch_program(num):
if num == 1:
subprocess.Popen(str(ServerLaunchBat), shell=True, cwd=ServerLaunchBat.parent)
elif num == 2:
subprocess.Popen(str(ClientLaunchBat), shell=True, cwd=ClientLaunchBat.parent)
is the same
Just different variables
def launch_server():
subprocess.Popen(str(ServerLaunchBat), shell=True, cwd=ServerLaunchBat.parent)
def launch_client():
subprocess.Popen(str(ClientLaunchBat), shell=True, cwd=ClientLaunchBat.parent)
Yeah I'm saying why make them into two functions
Also just realized a way to make it even more optimized and smaller
gonna do that rq
personal preference probably
in my mind i think of those two of doing different things so i'd split them into different functions
If you want to expand or change this program in the future, splitting separate logic in separate functions can make it easier to reason about and test your program
I mean you could just make more arguments couldn't you?
with python you can use r'' to not need to do all the inverted slashes if you prefer
something = Path(r'C:\Program Files\whatever')
renaming Path to P is kind of an anti-move; just makes it less clear and doesn't really help anything
# cleaner (another style choice)
VCProjectPath = Path.home() / Path(r"Downloads\RVLATESTFORREAL\Prod\VPS Game Modes\x64\Release")
unused variables looks like
ServerStr = str(ServerLaunchBat)
ClientStr = str(ClientLaunchBat)
I know
# don't use the var name "type"
def delete_old_dll(type):
if you must use type, use _type, but rather to use dll_type or so
Wait why would you do Path.Home and then put the path
or youre comparing them
not comparing, combining like you are
Path(r'C:') / Path(r'Program Files\Something')
don't need to do the / 'string' / 'other string' stuff
don't use random numbers for types like this
be explicit what those mean
for example
command=lambda: launch_program('Server')
first it makes your code more clear, then you realize you can do loops easier, and so on
I didn't combine them, wouldn't you do
VCProjectPath = P(r"Downloads\RVLATESTFORREAL\Prod\VPS Game Modes\x64\Release")
Yeah
But you said
VCProjectPath = Path.home() / Path(r"Downloads\RVLATESTFORREAL\Prod\VPS Game Modes\x64\Release")
Why would we go Path.home then do the direct path instead of just
just doing the exact same thing as you but not using multiple strings
VCProjectPath = P.home() / "Downloads" / "RVLATESTFORREAL" / "Prod" / "VPS Game Modes" / "x64" / "Release"
hm
you can combine all those strings
VCProjectPath = P.home() / Path(r"Downloads\RVLATESTFORREAL....")
it is the same but smaller
And my question is wouldnt you just put one path, without the P.home()
I would yes
don't you want to start from home
Oh π
doing it that way starts from current working directory
Sorry yeah my brains going insane rn I guess
I didn't realize that and now it clicked in
If I were to do that I would just put the whole path then, the drive letter and everything
But yeah Path.home() does the same thing, just looks weird to me
instead of using var name to store key information, use dictionary
LaunchBat['Client'] =
Before you said that I did indeed fix it and changed it to this
BatList = {
1: P("D:/Rumbleverse Launcher Preset/Server Patch/Rumbleverse/StartServer.bat"),
2: P.home() / "Desktop" / "Desktopped" / "dl" / "rubbleverse" / "ARCHIVEDRumbleverse" / "Rumbleverse" / "OpenAndInject.bat"
}
def launch_program(num):
subprocess.Popen(str(BatList[num]), shell=True, cwd=BatList[num].parent)
And I can go ahead and clean those paths up
then when you use proper 'type' instead of 0 and 1, you don't need to duplicate the Popens
You well on your way!
as you can see it's all just little nitpicky stuff and style choices etc for the most part π
soon you should/could start to move more to classes, as it cleans a lot of this stuff up
Yeah I was working on classes in the past
I'm simultaneously slowly learning C++ at the same time lol
I just went back into Python today after like a month
Yeah no it makes alot more sense now since if you didn't put P home you would have to put the drive letter and the user and everything
it works but it has this really ugly color style
look into using Guard-If statments, instead of nesting everything within if-else
Could you give an example? I'm more visual
/ forward slash is also valid iirc O.o
Yeah I ended up reverting to it lol
a quick snippet -
from pathlib import Path
def move_file(old_loc: Path, new_loc: Path):
if not old_loc.exists():
log.insert(tk.END, f'Failed to find the new File in {old_file}\n')
return
try:
shutil.copy(old_loc, new_loc)
log.insert(tk.END, f'Successfully transferred the new File.\n')
except Exception as e:
log.insert(tk.END, f'{e}\n')
move_file(NewDLL, ServerPath / OldDLLName)
I tried making it a bit more reusable, by using arguments instead of global variables.
So by Guard-If statements you mean more arguments to make reading all of it less?
My go to is dumbed down explanations so if thats correct or not it would help me understand lol
Oh I see so its more simplified as well, its actually kinda the opposite
I've made 2 changes to your code.
- is flatteting the
if-else-
#from this
if something:
print("Some very Large Code . . .")
...
else:
print("Nope.")
# into this
if not something:
print("Nope.")
return
print("Some Very Large Code . . .")
...
- Removing the use of global variables, and replacing it with local ones/as a function's arguments.
So if not then we return
if so we continue
so the if so we don't have to type its just there already
This is the changes I've currently made
def delete_old_dll(replace):
clear_button.invoke()
if not OldDLL.exists():
if replace:
log.insert(tk.END, f'Failed to delete, DLL already gone.\n')
return
log.insert(tk.END, f'Failed to delete, DLL already gone.\nMoving new DLL...\n')
move_new_dll()
try:
recycle(OldDLL)
if replace:
log.insert(tk.END, f'Successfully removed old DLL.\n')
return
log.insert(tk.END, f'Successfully removed old DLL.\nMoving new DLL...\n')
move_new_dll()
except Exception as e:
log.insert(tk.END, f'{e}\n')
return
btw, if you're going to pass tk.End every time you call log - you might as well wrap it with a short function.
like
log_end = lambda *args, **kwargs: log.insert(tk.End, *args, **kwargs)
``` or
```py
def log_end(*args, **kwargs):
log.insert(tk
End, *args, **kwargs)
that is ultra confusing
I mean I get it, but the code I don't.
These special parameters allow functions to take arbitrary amounts of positional and keyword arguments. The names args and kwargs are purely convention, and could be named any other valid variable name. The special functionality comes from the single and double asterisks (*). If both are used in a function signature, *args must appear before **kwargs.
Single asterisk
*args will ingest an arbitrary amount of positional arguments, and store it in a tuple. If there are parameters after *args in the parameter list with no default value, they will become required keyword arguments by default.
Double asterisk
**kwargs will ingest an arbitrary amount of keyword arguments, and store it in a dictionary. There can be no additional parameters after **kwargs in the parameter list.
Use cases
- Decorators (see
/tag decorators) - Inheritance (overriding methods)
- Future proofing (in the case of the first two bullet points, if the parameters change, your code won't break)
- Flexibility (writing functions that behave like
dict()orprint())
See /tag positional-keyword for information about positional and keyword arguments
@potent plank Thanks for all the help, I've been working on super optimizing it
I'll send the final result in a few and I would like to see what you think
I followed your advice
This help channel has been closed and it's no longer possible to send messages here. If your question wasn't answered, feel free to create a new post in #1035199133436354600. To maximize your chances of getting a response, check out this guide on asking good questions.