|
Hey folks. I've been working on a small python project for a bit now and I'm happy enough with the implementation that I'd like to try my hand at packaging it up and throwing it onto PyPi so people can try it out. I'm about 95% of the way there, but I have two outstanding questions that I can't find a way to address due to the search terms being too generic (and a general lack of understanding on my part). 2. Is there any sort of inbuilt functionality to have the package add itself to the system path or have the package install itself to a location within the path? I apologize if this it overly basic, anything I can try to google on the matter is from an end user perspective and doesn't have too much play in this area. Edit2: Ok, after some futzing around it looks like the root of the issue was that I needed to set up a main() function and then call that into the whatsits and that appears to have sorted things out nicely. If anyone would be interested in trying out the module I'd be interested in hearing feedback: https://test.pypi.org/project/streamers/ If anyone is interested, the code repo is here and I'd really appreciate any feedback that could be given. I've not done programming proper in a long time and even then that wasn't in the world of Python. Warbird fucked around with this message at 00:23 on Jul 16, 2022 |
# ? Jul 15, 2022 20:59 |
|
|
# ? May 30, 2024 13:42 |
|
Oh my god. I've been fighting with pip/setuptools for hours trying to find out why the hell the requests library dependency wasn't being found and pulled down. As it turns out, requests doesn't have a presence on the test PyPi setup and since my package was hosted there pip was checking it instead of the real deal and erroring out. While I can see that as things working as designed it really should be documented somewhere, but I'm not sure if that's a setuptools bug or something to do with pip itself.
|
# ? Jul 16, 2022 03:57 |
|
QuarkJets posted:I don't know of any decent class tutorials because every single one that I've ever seen deep throats the OOP cancer You gotta be more specific about wtf this is, because classes are deeply tied to OOP. Edit: Missed that you were replying to someone, thought you were asking for a tutorial. My bad. Falcon2001 fucked around with this message at 01:16 on Jul 17, 2022 |
# ? Jul 17, 2022 00:49 |
|
Seventh Arrow posted:Lo and behold, the same printout with half the calories! Or something. Would there ever be a reason to use .format() or a string concat instead of f-strings? Two things here - for starters, the biggest reason I've seen to use .format() is if you want to save a template and use it somewhere other than where it's being interpreted. For example, in a piece of software I maintain, we have some basic templates for the small amount of human readable outputs we do (emails/tickets/etc). These are stored in text files and have placeholders for {email_address} etc throughout. But for most smaller stuff, f-strings are great and you should stick to them. Second off, the whole classes thing. I really liked Automate The Boring Stuff as my intro to programming, so here's his chapter from another book on classes - I haven't read it, but in general these books are well recommended, so try it out: http://inventwithpython.com/beyond/chapter15.html IMO: Classes are basically the blueprints for objects that form the backbone of Object Oriented Programming. A class defines details about the object, such as attributes (what is this object?) and methods (what can this object do?) - so for example, you have the classic animal OOP example: code:
code:
QuarkJets above referred to the "OOP cancer", which, without speaking for them too closely, generally refers to how much of a tangled spaghetti mess poorly written OOP can be when you start getting into inheritance/etc. In general though, if you're writing Python, you need to understand OOP principles because Python is inherently OOP by design, and the majority of software written in it adheres to OOP practices. There's lots of footguns in OOP, mostly around things like maintainability of code, but there's also extremely robust discussion around avoiding those footguns and writing better code outside of it, all of which is probably past your current skill / knowledge level, so I wouldn't worry about it too much.
|
# ? Jul 17, 2022 01:35 |
|
Thanks! I will take a look at Al Sweigart's chapter - although later on in the Codecademy course they had a project that helped me get a better idea of how classes are used and what they're good for: https://gist.github.com/jalcoding8/fcac42c43d378c6943274ece219bde0f I could see how the Business could contain the Franchise and the Menu, and the Franchise could contain the Menu, and so on; and how they could also have functions that interact. I'm curious though - the order of stuff doesn't seem to matter for the most part. Like if the "Menu" class was before "Franchise", would the "calculate_bill" function (line 43) still work?
|
# ? Jul 17, 2022 14:33 |
|
Seventh Arrow posted:Thanks! I will take a look at Al Sweigart's chapter - although later on in the Codecademy course they had a project that helped me get a better idea of how classes are used and what they're good for: The order doesn't really matter (There's a BUT there around things like type hinting but it's pretty minimal) because you define your classes before you start actually executing code. Everything inside a class is a blueprint, so it's executed when you create a new object from that class, but the stuff starting on line 54 is actually code that's being executed. So if you tried executing that code before you defined the class (like say, move it to line 2) it will fail. Edit: a side interesting note: every time you import a module, it basically goes through and interprets all the code in there, which is why you see the weird pattern sometimes of if __name__ == "__main__" pattern in modules/scripts sometimes, because that basically lets you write code that won't be executed on import, only if you're running the file directly. Falcon2001 fucked around with this message at 20:01 on Jul 17, 2022 |
# ? Jul 17, 2022 19:30 |
|
I ran into a challenge where I think my solution was more efficient than the official solution, but I have this feeling that I'm overlooking something. The challenge was to use a function that takes a text string and returns a new string with every other letter. The official solution was as follows: code:
results in 'Cdcdm' This was my solution: code:
results in 'Cdcdm' Is there something I'm overlooking, or is it really that simple?
|
# ? Jul 18, 2022 02:30 |
|
No, that works fine, maybe they just wanted to teach for loops and range rather than slices at that point.
|
# ? Jul 18, 2022 02:37 |
|
Seventh Arrow posted:I ran into a challenge where I think my solution was more efficient than the official solution, but I have this feeling that I'm overlooking something. You could even just do code:
Not sure which one works out to be more efficient, but you could figure it out easily enough using timeit.
|
# ? Jul 18, 2022 02:40 |
In fact, the use of new_string = " " and then concatenating on to it results in " Cdcdm" with a leading space. That's easily fixed but yeah, just return that directly. Or if you super duper wanna force it into a string, code:
|
|
# ? Jul 18, 2022 02:43 |
|
The next exercise is similar, returning a string in reverse order. Their solution: code:
gets the result ymedacedoC My (new, goonified) solution: code:
gets the result ymedacedoC The challenge doesn't mention anything about teaching loops or range. Guess they want to show another way of doing things!
|
# ? Jul 18, 2022 04:34 |
|
Their solution is dumb and bad, holy smokes. If they absolutely had to use a for loop the least they could do is iterate over the characters instead of using indexingPython code:
|
# ? Jul 18, 2022 06:05 |
|
fisting by many posted:No, that works fine, maybe they just wanted to teach for loops and range rather than slices at that point. This is absolutely the point, and worth considering. They have a syllabus and these contrived examples have been designed to help teach you concepts for that syllabus, they're not supposed to be the "objective best all-context solution" for whatever the issue is - if the premise of the issue even makes any sense at all. It's just an educational tool to get you practising whatever the week's topic is e: I'm reminded of taking beginner (human) language classes and there was some guy I got paired with on some little "using the vocabulary provided and the grammar you know, have a conversation about what you did this weekend" task, and he refused to do it because none of the vocabulary covered what he did this weekend. A modern day George Washington boofhead fucked around with this message at 09:24 on Jul 18, 2022 |
# ? Jul 18, 2022 09:20 |
|
boofhead posted:They have a syllabus and these contrived examples have been designed to help teach you concepts for that syllabus, they're not supposed to be the "objective best all-context solution" for whatever the issue is - if the premise of the issue even makes any sense at all. It's just an educational tool to get you practising whatever the week's topic is
|
# ? Jul 18, 2022 20:44 |
|
Fair Personally in a professional environment I'd just give them one of the old Python code:
|
# ? Jul 19, 2022 14:51 |
|
This is useful in those situations where you get paid by the line!
|
# ? Jul 19, 2022 15:28 |
|
So what I came up with on this challenge is pretty close to what their solution was. The problem is that I'm not sure how or why it works. Here's the code: code:
But I'm not getting why it's returning the values instead of the keys. Shouldn't total += my_dictionary[k] be summing the keys instead of the corresponding value? And how would you do it if you did need to add up the keys instead of the values?
|
# ? Jul 20, 2022 06:43 |
|
Seventh Arrow posted:So what I came up with on this challenge is pretty close to what their solution was. k is the key, my_dictionary[k] is the value.
|
# ? Jul 20, 2022 07:01 |
|
In lists, you retrieve the value of an item in it by using its index.Python code:
With dictionaries, code:
|
# ? Jul 20, 2022 07:23 |
|
Seventh Arrow posted:So what I came up with on this challenge is pretty close to what their solution was. k is the key, my_dictionary[k] is the value. So if you did need to add up the keys you could just sum over each k instead of my_dictionary[k] code:
code:
QuarkJets fucked around with this message at 08:12 on Jul 20, 2022 |
# ? Jul 20, 2022 08:06 |
|
Thanks for the explanations!
|
# ? Jul 20, 2022 12:30 |
|
Seventh Arrow posted:So what I came up with on this challenge is pretty close to what their solution was. FYI, you don’t need .keys() here. Iterating over a dict iterates over the keys by default. So you could just use for k in my_dictionary and leave the rest the same. It’s equivalent. But the better way to do it in this case is the sum() + generator comprehension above anyway. Jigsaw fucked around with this message at 12:38 on Jul 20, 2022 |
# ? Jul 20, 2022 12:36 |
|
Jigsaw posted:FYI, you don’t need .keys() here. Iterating over a dict iterates over the keys by default. So you could just use for k in my_dictionary and leave the rest the same. It’s equivalent. boo ambiguity, boo
|
# ? Jul 20, 2022 23:27 |
|
CarForumPoster posted:boo ambiguity, boo
|
# ? Jul 20, 2022 23:58 |
|
ExcessBLarg! posted:While I think there's good argument that items() should have been the default iterable view of a dictionary, I wouldn't say this behavior is particularly ambiguous. Depends on how well controlled the input is. If you're sure its always getting a dict, then you'll always get the same behavior. If some bastard coated bastard ships you a string or a list you might now have anomalous behavior rather than an AttributeError
|
# ? Jul 21, 2022 22:01 |
|
Well I managed to solve something by my very own self with just a search engine and bucket full of tears. The latest challenge was thus: My original code was thus: code:
earned me this precious nugget: quote:TypeError: 'int' object is not iterable I'll spare you the parts with the tears and the alcohol consumption and the long walk under a full moon but anyways I got the bright idea to see just what happens when you run the following in a separate jupyter window: code:
So after a few mutations, I wound up with this: code:
code:
Seventh Arrow fucked around with this message at 04:16 on Jul 22, 2022 |
# ? Jul 22, 2022 03:51 |
|
Seventh Arrow posted:Well I managed to solve something by my very own self with just a search engine and bucket full of tears. I’m really not sure what their fetish for explicit “for” loops over comprehensions is. I get the sense that the course wasn’t really developed with Pythonic code in mind. Here’s a solution that uses a dict comprehension to do it all in one go: code:
code:
Jigsaw fucked around with this message at 05:42 on Jul 22, 2022 |
# ? Jul 22, 2022 05:24 |
|
Seventh Arrow posted:Well I managed to solve something by my very own self with just a search engine and bucket full of tears. code:
1. For each word in the list of words 2. Create a list containing the lengths of all of the words 3. Create dict containings all of the words and word lengths 4. End loop over words 5. Return a dictionary. A list comprehension and a dict comprehension are kinds of loops, so you have nested loops. In the first iteration of the outer loop you complete the work of finding all of the word lengths and creating a dictionary mapping all of the words to their lengths. In each subsequent iteration, you're re-computing the same results and re-assigning them to the old variables, effectively throwing away the old results. You only need the first iteration of the loop, e.g. you don't need the outer loop at all. Here's how I'd do it: code:
|
# ? Jul 22, 2022 05:36 |
|
I’d like to traverse a set of Windows (sub)directories (including all subdirs) containing tens of thousands of files and find all duplicate files, including those in different directories, and including those with “- Copy” or “(1)” suffixes. The report the absolute path of dupes so I can decide which to delete later. Anyone have an idea for an efficient way to do this? I could also use powershell but this seems more like a short python script. pmchem fucked around with this message at 14:15 on Jul 22, 2022 |
# ? Jul 22, 2022 14:11 |
|
You could probably do this with os.walk(). You would need to do something to canonicalize the file name, e.g. handle the “- Copy” and “(1)” suffixes, but once you have that you can keep a dictionary of file names, checking if the key exists each time (if so, it’s a duplicate). Duplicates can go into a separate list or whatever that you dump at the end. Obviously, you’ll want to keep the actual file name around to go into this list, rather than the canonicalized version.
|
# ? Jul 22, 2022 14:58 |
|
Apex Rogers posted:You could probably do this with os.walk(). You would need to do something to canonicalize the file name, e.g. handle the “- Copy” and “(1)” suffixes, but once you have that you can keep a dictionary of file names, checking if the key exists each time (if so, it’s a duplicate). Duplicates can go into a separate list or whatever that you dump at the end. Obviously, you’ll want to keep the actual file name around to go into this list, rather than the canonicalized version. Keep a dict[str, list[Path]] where the key is the canonicalized name, and the value is a list of all file paths associated with it. Iterate over the whole directory with os.walk() and then every file just figure out what it's canonical name is, then toss it in the dictionary. One final iteration over the dict to filter out any entry with a value length of 1 or less, and boom, there you go.
|
# ? Jul 22, 2022 17:54 |
Jigsaw posted:I’m really not sure what their fetish for explicit “for” loops over comprehensions is. I get the sense that the course wasn’t really developed with Pythonic code in mind. Here’s a solution that uses a dict comprehension to do it all in one go: Seems like it’s an introduction to programming that uses python, not an introduction to python. I’d figure that for beginners, using features that are available in lots of languages is better than using very pythonic solutions.
|
|
# ? Jul 22, 2022 19:05 |
|
a foolish pianist posted:Seems like it’s an introduction to programming that uses python, not an introduction to python. I’d figure that for beginners, using features that are available in lots of languages is better than using very pythonic solutions. Ah, that’d make a lot of sense.
|
# ? Jul 22, 2022 19:41 |
|
Speaking of general design pattern problems: I have some questions about Dependency Injection. I'm reworking some of my code, and one area in particular has a lot of dependencies because it deals with a large number of various internal services. This is all functions, no classes in this module, for context. My initial setup is setting up a dataclass that just holds those dependencies, initializing it at the entrypoint to this portion of the codebase with a factory function, and then passing that down as the calls flow through. This allow for dependency injection as I have a factory function that builds it the 'default' way, but I can also easily pass in appropriately configured mocks / test replacements for testing. Is there any significant disadvantage to doing this?
|
# ? Jul 22, 2022 21:19 |
|
The trouble that I usually see is people use dependency injection to just move an obscure environment variable from one place to another, passing it in with literally the same variable name without thinking about what their code actually does. On top of the more well-known advantages, another big advantage of using dependency injection is that you can write code that is easier to read and self-documenting. If you're refactoring anyway then you may as well write the best possible signatures I think that the biggest pitfall here is that you are probably making changes that aren't backwards compatible, so you have to be carefully looking for broken code and controlling your version numbers and package dependencies. The specific approach you're using is good and is the very common "put the arguments in a struct" mode of simplifying overly long function signatures. Be careful about adding too many parameters that aren't actually common to multiple services, e.g. your functions should only receive parameters that are relevant to them; otherwise this can create confusion later. Ask yourself, which of the parameters in this dataclass is actually used by this function?" The answer should be "all of them" QuarkJets fucked around with this message at 21:58 on Jul 22, 2022 |
# ? Jul 22, 2022 21:56 |
|
QuarkJets posted:The trouble that I usually see is people use dependency injection to just move an obscure environment variable from one place to another, passing it in with literally the same variable name without thinking about what their code actually does. On top of the more well-known advantages, another big advantage of using dependency injection is that you can write code that is easier to read and self-documenting. If you're refactoring anyway then you may as well write the best possible signatures Thanks! In this case it's a reasonably shallow section of code that just happens to have a lot of weird api calls to make. Unfortunately, this also means that the dependency chain is...more complicated than most. For example, Function X calls API 1 for all services, then I filter based on a call to API 2, and then pass to a subfunction that does API 1 and 3, but not two. But it in turn has a helper function that does call to API 2. This all probably means I didn't do a good enough job writing this up in the first place, but it does mean that while a function might not need a specific dependency, a helper function it relies on does. Luckily this madness is confined to this particular module and won't pollute the rest of the codebase.
|
# ? Jul 22, 2022 22:47 |
|
QuarkJets posted:
Yeah at this point I feel like I'm just taking blocks of code and mashing them together based on what's in my continually-updating cheat sheet. I want to get a deeper understanding of how these things work but I think it's just part of the process and I need to be patient. I think it's sort of like how at the start every musician sounds like their favorite musician until they start expanding their musical vocabulary. I will probably get a tutor from fiverr later but I want to kind of struggle through the course first and see how much I can figure out on my own.
|
# ? Jul 24, 2022 19:55 |
|
A good exercise is to open up a terminal and copy in code, run it, and start printing variables to see what's going on. Less is more here, inspect the results of each line if you aren't sure what's going on. A little more advanced than that would be using a debugger or a jupyter notebook. Basically execute one line and then check to see see what happened to each variable in the line. Pretty quickly you'll figure out how things work "run some simple set of lines and see what it does" is a valuable habit that I still use
|
# ? Jul 24, 2022 20:27 |
|
I will also say that if you just keep writing more code you can often achieve understanding through repetition. Honestly it's the way I got to the point where actual computer science theory started to stick: I did a ton of code katas on sites like CodeWars and Leetcode - I'd start with the ones with the highest completion rate, then try and brute force my way through it, googling anything I didn't understand. This isn't perfect, but at least for me I really struggle with theory when I don't have a way to tie it to concrete examples. Example: Dependency Injection seemed like the dumbest pattern in the world to me like 9 months ago. My only experiences with it had been the sort of 'magic pile of bullshit' added to big web framework startup sections, and it just seemed mystical to me. Why are you adding all these things here? Why not just use them where they're needed? Your code looks awful! Sure, I could read about why they were useful, but honestly it didn't click until: I'm working on an escalation module for a service I own and part of that is mail; I have a mailer class that handles all my mail workflows, which are pretty minor. When I wrote this originally I just had singletons setup for the Mailer class, and no unit tests because my mentor at the time didn't think it was important. Now I'm coming back to my code after a month or so away from it and my immediate thought was 'well gently caress, how do I know this WORKS?' 'I guess I can do a dry-run of our stuff? Well poo poo, dry-runs don't process mail, on purpose, to avoid any accidental mailing.' 'Huh. I need like a 'send-mail-anyway-dry-run' option...But that seems like a weird edge case. What if I added mailing to the dry run, and then just had a neutered option? Well that'd be hard to do because I'd need to ohhhhh make a new mailer class with the send functionality nerfed and inject the dependency.' The most obvious problem here is I should have been pushed to test my code when I originally wrote it, but now I know and will improve over time.
|
# ? Jul 25, 2022 17:42 |
|
|
# ? May 30, 2024 13:42 |
|
Can someone tell me whats going on with this "fluent interface" poo poo. https://github.com/kkroening/ffmpeg-python Because it kind of makes me feel like bullying a javascript coder, and I'm not entirely sure why. Is this actually a *thing* in python now? or is this dude just abusing import semantics? Cos it doesnt *look* pythonic, but I'm old and have bad knees and dont like kids on lawns or something.
|
# ? Jul 26, 2022 07:20 |