mcc,
@mcc@mastodon.social avatar

My constant experience with Python over the last ~16 years is I start writing it and it's like, wow, this is so easy, this is great! And then I run my program, and invariably it fails with an inscrutable error/exception 4 layers deep in someone else's library, code I know nothing about— in this case, a wav file library claiming that the number 960 is "not a valid shape"— and I realize that maybe I actually hate Python

stiv,
@stiv@mastodon.social avatar

@mcc I remember when I started being sort of ok with template meta-programming it hit me that the awful error messages people complained in C++ were just a compile-time form of the runtime error stack traces I'd see in Python, both of which arose from designing code around duck typing.

I used to complain if people didn't check common arg types for null at the top of library functions in Java, and thus found it bizarre that everyone was OK with libraries in Python working this way.

Asariel999,

@mcc At least you understand what you're doing. I had barely started reading about Python and it fells like a foreign language. And I can switch from Spanish to English in a flash.

BoredomFestival,
@BoredomFestival@sfba.social avatar

@mcc I stand by my assertion that any Python program longer than a page or three should be rewritten in something more statically/ strongly typed. Apologists will say "proper tooling/IDE support mitigates this" but I reject the notion that good language design requires more than a text editor for effective use.

zenkat,
@zenkat@sfba.social avatar

@mcc tl;dr -- you don't hate Python, you hate Python library developers.

mcc,
@mcc@mastodon.social avatar

@zenkat If I didn't rely on Python library developers I could just write in Lua !!!

zenkat,
@zenkat@sfba.social avatar

@mcc true dat

recursive,
@recursive@hachyderm.io avatar

@mcc python really taught me to dislike dynamic typing.

simon_brooke,
@simon_brooke@mastodon.scot avatar

@mcc It's what you get with a language many/most of whose users are not primarily software people. JavaScript is the same. Libraries are of very varying quality and even the good ones change all the time, meaning there's a huge maintenance overhead.

It's great that languages are approachable by non-specialists, but...

nervous_jesse,
@nervous_jesse@mathstodon.xyz avatar

@mcc I just stick with “I hate Python” and never touch it

traumaphoenix,
@traumaphoenix@chaos.social avatar

@mcc honestly, yeah same

i wish there was an easier way to write type checks for the big complex types you can create with the typing import

as it stands today, you have to dynamically check every attribute conforms to the type hint written 🦋

mmby,
@mmby@mastodon.social avatar

@mcc python is sadly also a headache to embed as a scripting language, precisely because of the universe of useful libraries and the dependency nightmares that brings

I like using python a lot, with numpy, scipy, matplotlib, scikit etc. but it's sadly not very portable at all

rf,
@rf@mas.to avatar

@mcc from the other end, super used to Python, have worked in it a long time, but whenever I mess around in a language with static types and good tooling I'm always surprised when the time from first build to first successful run is so brief

whitequark,
@whitequark@mastodon.social avatar

@mcc this is why like half of Amaranth is diagnostics checking types of stuff, yeah

Flux,
@Flux@wandering.shop avatar

@mcc and then someone deploys it to production and wonders why the AWS bill is through the roof.

tristanpalmgren,

@mcc In this house, all numbers are valid shapes.

mcc,
@mcc@mastodon.social avatar

This is definitely a problem that typing would have prevented, because if something was wrong with the data I was passing in, it would have been caught at the library boundary rather than deep inside library code.

Gradual typing is something else I want to love. But TypeScript/Typed Python make me think that maybe the appropriate approach is for typing to be optional within a program but mandatory at all module/library boundaries.

phillmv,
@phillmv@hachyderm.io avatar

@mcc

i find typing within Ruby to be abominable but love the idea of defining typed method signatures. all the jump to def and most of the safety

gureito,
@gureito@peoplemaking.games avatar

@mcc i'm getting more and more behind the idea that "gradual typing" should mean you gradually filling in the types the compiled inferred wrong and thus failed to compile 😅 your point is a perfect enabler, as the library frontier would have well-defined types that percolate through the program code 😊

SonnyBonds,
@SonnyBonds@mastodon.gamedev.place avatar

@mcc Maybe TypeScript works like this (not sure), but in good ol' ActionScript (and later HaXe) it's got gradual typing but having a type is the default. So, you need to specify a type, but it can be */Dynamic. (Possibly "any" in TypeScript?)

It makes the default typing static, and while it's easy to break out of it where applicable that's an explicit choice.

mcc,
@mcc@mastodon.social avatar

@SonnyBonds So the thing with both TypeScript and Python is they start with a language with no types, and then they added types after a large ecosystem of libraries was written.

I don't think your suggestion necessarily fixes the problem. I guess what you're proposing is in such a world the libraries I consume would simply not contain typing errors, because they'd have been pushed to "usually" use types. I don't trust library authors that much.

mcc,
@mcc@mastodon.social avatar

@SonnyBonds As for TypeScript specifically, it's relatively strict about where it requires types by default, but it doesn't matter, because you can simply write an entire file in JavaScript and then it's fully untyped.

SonnyBonds,
@SonnyBonds@mastodon.gamedev.place avatar

@mcc Yeah sorry I didn't mean it as a fix for existing systems. I just mean it would've been a better choice from the start, since it encourages better type use. That ship has sailed.

mcc,
@mcc@mastodon.social avatar

Moving from general thoughts to specific— I thought this would turn out to be me making an error with the data type I passed in. Except no. I checked and I defs put in a regular Python array of length 960. The (960,) 1-tuple is just the dimension of my array, and the "Invalid shape" appears to be something emitted from Numpy, which this wav library inexplicably uses. So I'm gonna have to learn Numpy to debug this library to write a file. Nightmarish. It might be quicker to write my own wav lib

fraca7,

@mcc Ouch, numpy. Condolences.

delta_vee,
@delta_vee@mstdn.ca avatar

@mcc Genuine question and not sarcastic: do you consider the shapes of arrays to be types in themselves?

mcc,
@mcc@mastodon.social avatar

@delta_vee In many languages, it's certainly part of the type, yes. And at the external interface boundary with which I am interacting with this library, there are no types in scope which are dynamic array types. I am passing in regular Python arrays, for which shape (dimension, if not size) is absolutely visible, mandatorily, to the type system.

pitbuster,
@pitbuster@lile.cl avatar

@mcc uuuf, the amount of times I've had to delve into library code because the documentation sucks and there is no other way to debug

mcc,
@mcc@mastodon.social avatar

So after reading the source of this library, it turns out that "Invalid shape: (960,)" means "I was passing in one array of channel-interleaved sound samples, but it wanted an array of two arrays". Which in my opinion is not a clear error message since instead of describing the error in terms of the semantics of the library (stereo data expected, mono data received) it described it in terms of some dynamic-dimension scientific computing array type it's using internally

mcc,
@mcc@mastodon.social avatar

UPDATE: I was incorrect that the problem was fixable. After switching to non-interleaved data it tells me "(2, 48)" is not a valid shape.

galibert,
@galibert@piaille.fr avatar

@mcc I hate when my programming language tells me I'm out of shape, I know that already

stacey_campbell,
@stacey_campbell@aus.social avatar

@mcc I don't know who coded up these error messages, but if they kick over to work at AMD/Xilinx they will be well compensated.

mcc,
@mcc@mastodon.social avatar

Okay. I think this library was simply a honeypot. After understanding what format it wants the data in, and making a list of 3-4 bugs to file ranging everything from "unhelpful error messages" to "your pip dependencies are incorrect" to "the link to your current documentation is dead", I open the file I made and the wav file consists entirely of zeroes. The input, by observation using "print", is not zeroes. The library apparently does nothing at all.

GreenSkyOverMe,
@GreenSkyOverMe@ohai.social avatar

@mcc 😱

alexch,
@alexch@ruby.social avatar

@mcc

“You can have any output you like, as long as it’s all zeroes.” ;-)

mcc,
@mcc@mastodon.social avatar

Rubbing eyes Alright. So once it became clear that (although it advertises use with or without numpy) this library does not work without numpy, I decided to throw good time after bad and use numpy. The library now works.

I do have a numpy question now.

I build my array of data gradually. In my working code, I build a 2d python array [[],[]], then pass it to np.array.

Is there a way to gradually build/append an np array?

Do I have to first preallocate a size with zeroes() then use put()?

Scmbradley,
@Scmbradley@mathstodon.xyz avatar

@mcc yeah preallocating is going to be easier, I think. Though depending on how you're building,you could use concatenate?

mcc,
@mcc@mastodon.social avatar

@Scmbradley I just feel like I'm creating so much garbage. I thought the entire point of numpy was it let you do arrays without allocating lots of temporaries.

mcc,
@mcc@mastodon.social avatar

@Scmbradley Is concatenate an in-place operation or does it create a new array?

Scmbradley,
@Scmbradley@mathstodon.xyz avatar

@mcc I think numpy functions are rarely in place. Concatenate isn't, for sure.

But with concatenate,you can just concat a bunch of python lists. So you don't need to put all the intermediaries into numpy.

kleaders,
@kleaders@fosstodon.org avatar

@mcc you can. It's been a while since I've done it, but if I remember correctly you can .extend() an array with an array of the same shape.

jplebreton,
@jplebreton@mastodon.social avatar

@mcc np.append appends to a copy of the array given, i believe. so it's a new allocation, but it does give you what you want. i haven't deeply investigated the perf impact.

mcc,
@mcc@mastodon.social avatar

@jplebreton OK. So what I've got is a 2xVerylong matrix, and I am annoyed that constructing the matrix means making a Verylong number of 2-length arrays as garbage. So if the pure-numpy doing this means creating lots of numpy temporaries rather than lots of array temporaries it doesn't sound like a win.

jplebreton,
@jplebreton@mastodon.social avatar

@mcc it seems especially ill-suited for generating a series of WAV data! in my experience (esp writing Playscii) numpy gets used everywhere because it's the powerful swiss army knife (whose native parts seem to have pretty good performance, IME) but it ends up having a not-small impact on all the code that refers to it, and sometimes the ideal paradigms for numpy VS the client project don't match particularly well.

jplebreton,
@jplebreton@mastodon.social avatar

@mcc i'd be curious how people handle this kind of thing in languages that require you to think more about allocation, eg Rust - there's got to be some pattern that works well for "i'm recording sound and i don't know how long it's gonna be" (allocate in blocks as you go?) and i'd really hope numpy supports that.

bk1e,
@bk1e@mastodon.social avatar

@jplebreton @mcc Hmm, this crate supports appending: https://docs.rs/hound/latest/hound/struct.WavWriter.html

Does the Python soundfile package support appending? Maybe you can write multiple fixed-size chunks without building a single contiguous NumPy array.

bk1e,
@bk1e@mastodon.social avatar

@mcc @jplebreton If you can’t predict the total array length, would it be possible to generate the data in chunks? You could build a list of NumPy arrays and then concatenate them into a single NumPy array at the end.

This would avoid creating a list of 2-element sample lists or appending one sample at a time to the NumPy array (which would be slow if each append reallocates and copies the entire array).

bk1e,
@bk1e@mastodon.social avatar

@mcc @jplebreton Ok, the list & concatenate are unnecessary. You can use the SoundFile class to write multiple blocks of data to the file.

vfig,
@vfig@mastodon.gamedev.place avatar

@mcc @jplebreton rather than create python (nested) lists and convert them with numpy.array(), you can avoid garbage by creating a numpy array with numpy.empty() or numpy.zeros(). you can fill it by indexing or slicing, or from an iterable.

additionally, numpy treats array layout as distinct from storage; so you can create a long 1d numpy array of left,right,left,right samples, then set the array shape to (-1,2) so it is viewed the same as if it was an array of 2-element-tuples.

h0m54r,

@mcc @jplebreton What I’d do here is create a [VeryLongList, VeryLongList], then use np.asarray (and take the transpose of the result if you need the opposite ordering); this should create less garbage than using np.append. numpy is heavily optimised for doing operations on arrays that stay the same size. Preallocating (in chunks or otherwise) is another option as discussed elsewhere in the thread, and I think would have a lower memory overhead if that’s a concern.

ali1234,
@ali1234@mastodon.social avatar

@mcc growing a numpy array can be done but it requires allocating a new one and copying the old one into it so yes allocate the size you need with zeros().

mhoemmen,
@mhoemmen@c.im avatar

@mcc you remind me what a struggle it is to get some of my colleagues to write decent error checking

fishidwardrobe,
@fishidwardrobe@mastodon.me.uk avatar

@mcc A lot of Python code calls Numpy because it has "better" array handling, apparently. Seems like using an Apollo 11 main thruster at a BBQ to me…

bk1e,
@bk1e@mastodon.social avatar

@mcc The docstrings for this library indicate that it uses NumPy types in its public interface, so I think the authors expect you to learn NumPy in order to use it at all.

I would try reading a WAV file and seeing what array shape it returns. Maybe you need to transpose rows and columns?

DocBohn,
@DocBohn@techhub.social avatar

@mcc My best story about the importance of typing was a piece of code I wrote several years ago to help me manage a largish course. There was a bug in part of the code that paired students for group projects. I couldn't be bothered to hunt down the bug because I was the only person using it, and the erroneous output was easy enough to catch.

One summer as I was adding functionality, I decided to also add type inferences. Immediately my IDE said "Hey, you've got a bug here. You're assigning a Duck object to a Goose variable." (not the real class names)

mhoemmen,
@mhoemmen@c.im avatar

@mcc this reminds me also what a struggle it is to get some of my colleagues to write types other than "nested tuple"

mcc,
@mcc@mastodon.social avatar

@mhoemmen Oh… this one I may bear some degree of guilt on personally >_>

mhoemmen,
@mhoemmen@c.im avatar

@mcc they generally listen a bit better to "please use a named struct" than they do to "wouldn't it be nice if we added some input validation here"

  • All
  • Subscribed
  • Moderated
  • Favorites
  • random
  • ethstaker
  • DreamBathrooms
  • GTA5RPClips
  • magazineikmin
  • InstantRegret
  • cubers
  • thenastyranch
  • Youngstown
  • rosin
  • slotface
  • osvaldo12
  • ngwrru68w68
  • kavyap
  • everett
  • megavids
  • Durango
  • normalnudes
  • Leos
  • mdbf
  • khanakhh
  • tester
  • modclub
  • cisconetworking
  • anitta
  • tacticalgear
  • provamag3
  • JUstTest
  • lostlight
  • All magazines