Register a SA Forums Account here!
JOINING THE SA FORUMS WILL REMOVE THIS BIG AD, THE ANNOYING UNDERLINED ADS, AND STUPID INTERSTITIAL ADS!!!

You can: log in, read the tech support FAQ, or request your lost password. This dumb message (and those ads) will appear on every screen until you register! Get rid of this crap by registering your own SA Forums Account and joining roughly 150,000 Goons, for the one-time price of $9.95! We charge money because it costs us money per month for bills, and since we don't believe in showing ads to our users, we try to make the money back through forum registrations.
 
  • Post
  • Reply
Data Graham
Dec 28, 2009

📈📊🍪😋



First of all you're repeating yourself; you're doing the exact same random number generation thing both outside the while loop and inside it. If you find yourself doing that, you should be thinking "a) I should refactor this repeated code into a single method I can call multiple times; and b) I should rethink this while loop pattern so I only have to write it once in the first place".

Secondly you shouldn't have to do a query at all. Assuming (and if this is a bad assumption, disregard this suggestion) that the index is a unique column in your table, if you try to just insert a row with a pregenerated index that collides with an existing row, it ought to raise a DatabaseError (or something similar, I'm guessing this is sqlalchemy and I'm not sure what the exceptions look like). So what I would try is the "forgiveness rather than permission" approach, i.e.

Python code:
def generate_index(id: int, table_name: str):
        p_int = random.randint(1, 65000)
        p_salt = p_int.to_bytes(16, "little")
        return pyblake2.blake2b(data=bytes(id), salt=p_salt)

success = False
while success is False:
    try:
        insert_into_db(index=generate_index(my_id, my_table)
        success = True
    except DatabaseError:
        pass
That way you avoid the lookup of existing indexes, and you also avoid a race condition where another copy of the script might be checking for existing indexes at the same time. It'll just keep trying until it succeeds. (You can put some retry/countdown logic on it too so it errors out after like 100 tries or something, to avoid just going into an infinite loop.)

Data Graham fucked around with this message at 04:25 on Oct 1, 2023

Adbot
ADBOT LOVES YOU

Falcon2001
Oct 10, 2004

Eat your hamburgers, Apollo.
Pillbug
Why not use UUIDv4 instead of generating this weird custom hashing thing? It's basically guaranteed to not collide and v4 is generated from a seed. The collision chance of UUIDv4 is essentially zero - one explanation put it at 'generate a million UUIDv4s a day for 100 years and you'll have a 50% chance of a single duplicate.'

Son of Thunderbeast
Sep 21, 2002

Data Graham posted:

First of all you're repeating yourself; you're doing the exact same random number generation thing both outside the while loop and inside it. If you find yourself doing that, you should be thinking "a) I should refactor this repeated code into a single method I can call multiple times; and b) I should rethink this while loop pattern so I only have to write it once in the first place".

Secondly you shouldn't have to do a query at all. ... if you try to just insert a row with a pregenerated index that collides with an existing row, it ought to raise a DatabaseError (or something similar, I'm guessing this is sqlalchemy and I'm not sure what the exceptions look like). So what I would try is the "forgiveness rather than permission" approach,
Yeah, I recognized the repeated code as an issue even at the time, and was like "I'll fix that up when I have time or need to" and well here I am now haha. Yeah, it's sqlalchemy. Took a minute to get used to it but once I did it was great.

Huge thanks for the tip and example there. Honestly it just drives home the point that I need to finally get off my rear end and learn how to actually handle errors. Because yeah, my script would error when trying to insert the dupe index value, and the hackjob was just so I could get the errors off my back and push back having to learn how to deal with them properly. Guess that era's over!

Falcon2001 posted:

Why not use UUIDv4 instead of generating this weird custom hashing thing? It's basically guaranteed to not collide and v4 is generated from a seed. The collision chance of UUIDv4 is essentially zero - one explanation put it at 'generate a million UUIDv4s a day for 100 years and you'll have a 50% chance of a single duplicate.'
I'm assuming you mean uuid.uuid4()? I looked at UUID briefly but I think my lack of understanding led to me overcomplicating everything for myself. I'm pretty sure at the time I made the decision (at like 2am, also frustrated) I had convinced myself I absolutely needed some way to pass in a salt, so I skimmed right past the uuid stuff. Ended up trying a couple other cryptographic libraries and settled on pyblake2 because it wasn't a pain in the rear end to install (one of them kept yelling at me about wheels) and I was able to get it to do what I needed at the time. I think in retrospect uuid4 would have been the obvious choice

e: oh, I remember one reason why I didn't think to try it Data Graham's way at first, because the function in question makes several dataframes (each with its own function building it), generates an index for each, and then inserts them all to their various tables all at once at the end, so there's a lot happening between the generate and insert. I realize that's a design problem and I'll need to look at a deeper refactor later. e2: actually, now, since the design issue is blocking the fix, lol, dammit I was gonna play video games

Son of Thunderbeast fucked around with this message at 06:26 on Oct 1, 2023

QuarkJets
Sep 8, 2008

Data Graham posted:

First of all you're repeating yourself; you're doing the exact same random number generation thing both outside the while loop and inside it. If you find yourself doing that, you should be thinking "a) I should refactor this repeated code into a single method I can call multiple times; and b) I should rethink this while loop pattern so I only have to write it once in the first place".

Secondly you shouldn't have to do a query at all. Assuming (and if this is a bad assumption, disregard this suggestion) that the index is a unique column in your table, if you try to just insert a row with a pregenerated index that collides with an existing row, it ought to raise a DatabaseError (or something similar, I'm guessing this is sqlalchemy and I'm not sure what the exceptions look like). So what I would try is the "forgiveness rather than permission" approach, i.e.

Python code:
def generate_index(id: int, table_name: str):
        p_int = random.randint(1, 65000)
        p_salt = p_int.to_bytes(16, "little")
        return pyblake2.blake2b(data=bytes(id), salt=p_salt)

success = False
while success is False:
    try:
        insert_into_db(index=generate_index(my_id, my_table)
        success = True
    except DatabaseError:
        pass
That way you avoid the lookup of existing indexes, and you also avoid a race condition where another copy of the script might be checking for existing indexes at the same time. It'll just keep trying until it succeeds. (You can put some retry/countdown logic on it too so it errors out after like 100 tries or something, to avoid just going into an infinite loop.)

This is a great time to mention `suppress`, I like to recommend that for bare except blocks

Python code:
from contextlib import suppress
...
...
...
success = False
while success is False:
    with suppress(DatabaseError):
        insert_into_db(index=generate_index(my_id, my_table)
        success = True

Falcon2001
Oct 10, 2004

Eat your hamburgers, Apollo.
Pillbug

Son of Thunderbeast posted:

Yeah, I recognized the repeated code as an issue even at the time, and was like "I'll fix that up when I have time or need to" and well here I am now haha. Yeah, it's sqlalchemy. Took a minute to get used to it but once I did it was great.

Huge thanks for the tip and example there. Honestly it just drives home the point that I need to finally get off my rear end and learn how to actually handle errors. Because yeah, my script would error when trying to insert the dupe index value, and the hackjob was just so I could get the errors off my back and push back having to learn how to deal with them properly. Guess that era's over!

I'm assuming you mean uuid.uuid4()? I looked at UUID briefly but I think my lack of understanding led to me overcomplicating everything for myself. I'm pretty sure at the time I made the decision (at like 2am, also frustrated) I had convinced myself I absolutely needed some way to pass in a salt, so I skimmed right past the uuid stuff. Ended up trying a couple other cryptographic libraries and settled on pyblake2 because it wasn't a pain in the rear end to install (one of them kept yelling at me about wheels) and I was able to get it to do what I needed at the time. I think in retrospect uuid4 would have been the obvious choice

e: oh, I remember one reason why I didn't think to try it Data Graham's way at first, because the function in question makes several dataframes (each with its own function building it), generates an index for each, and then inserts them all to their various tables all at once at the end, so there's a lot happening between the generate and insert. I realize that's a design problem and I'll need to look at a deeper refactor later. e2: actually, now, since the design issue is blocking the fix, lol, dammit I was gonna play video games

So if all you're doing is generating a unique ID, and the actual length of that ID isn't particularly concerning from a performance standpoint, then a UUID is a great way to do that; UUIDv4 is deterministic, whereas UUIDv6 is not (it's more complex than that obviously, but that's a good starting point). The deterministic part is useful if you want to consistently produce the same UUIDv4 from source data.

boofhead
Feb 18, 2021

QuarkJets posted:

This is a great time to mention `suppress`, I like to recommend that for bare except blocks

Python code:
from contextlib import suppress
...
...
...
success = False
while success is False:
    with suppress(DatabaseError):
        insert_into_db(index=generate_index(my_id, my_table)
        success = True

Ahh that's neat, thank you

Data Graham
Dec 28, 2009

📈📊🍪😋



Seconded, that's rad

But yeah OP, mastering exceptions is one of those things you should definitely make time for, because it's not some kind of advanced afterthought system for dealing inelegantly with corner cases the way some languages treat it — in Python it's a robust, first-class and recommended pattern for handling certain kinds of logic flow. Once I started thinking of exceptions as a top-drawer tool just like for loops and class methods, it opened up a whole world of straightforward and concise code. Clearly there's always more to learn about them (case in point), but the fundamentals of them are real solid and pretty simple.

KICK BAMA KICK
Mar 2, 2009

Tiniest thing that would almost never cause a problem but would be hell to figure out if you weren't using an IDE or linter that would have already pointed it out: id is a built-in you should avoid shadowing with an argument of the same name.

Son of Thunderbeast
Sep 21, 2002

Falcon2001 posted:

So if all you're doing is generating a unique ID, and the actual length of that ID isn't particularly concerning from a performance standpoint, then a UUID is a great way to do that; UUIDv4 is deterministic, whereas UUIDv6 is not (it's more complex than that obviously, but that's a good starting point). The deterministic part is useful if you want to consistently produce the same UUIDv4 from source data.
Definitely remembering this for next time 🙏

QuarkJets posted:

This is a great time to mention `suppress`, I like to recommend that for bare except blocks
ooh nice! Thanks for this.

KICK BAMA KICK posted:

Tiniest thing that would almost never cause a problem but would be hell to figure out if you weren't using an IDE or linter that would have already pointed it out: id is a built-in you should avoid shadowing with an argument of the same name.
oh yeah, I was just quickly renaming some stuff before posting to make the code clearer, it's not actually called "id"

Data Graham posted:

Seconded, that's rad

But yeah OP, mastering exceptions is one of those things you should definitely make time for, because it's not some kind of advanced afterthought system for dealing inelegantly with corner cases the way some languages treat it — in Python it's a robust, first-class and recommended pattern for handling certain kinds of logic flow. Once I started thinking of exceptions as a top-drawer tool just like for loops and class methods, it opened up a whole world of straightforward and concise code. Clearly there's always more to learn about them (case in point), but the fundamentals of them are real solid and pretty simple.
Much appreciated! Sounds like a good environment to learn the next thing on my list, unit testing and test driven development :q:

e: I'm aware of pytest and have a tab open with the documentation, just haven't dipped my toes in yet

Son of Thunderbeast
Sep 21, 2002
Quick update, I did the refactor and the script is loving zooming now, even faster than before (and it wasn't that bad before i hosed it up), thanks for all the help!

Before it was like

Python code:
def worker(input):
  ls_func1 = []
  ls_func2 = []
  ...
  
  datadict = {
    "table1" : pd.DataFrame()
    "table2" : ...
    ...
    }

  grab X chunks of data to work on
  for each chunk:
  
    # indexes generated here, for every row
    afunction1(input) -> [{}]
    afunction2(input) -> [{}]
    ...
    
    # All rows for the chunk into a dataframe
    df_func1 -> DataFrame(afunction1).set_index("index")
    df_func2 -> DataFrame()...
    ...
    
    # Add df to list of dfs
    ls_func1.extend(df_func1)
    ls_func2.extend(df_func2)
    ...

  datadict = {
    "table1" = [ls_func1],
    "table2" = [ls_func2],
    ...
    }
  
  return datadict

def main:
  chunksdata = worker(input)
  for k in chunksdata:
    insert(dataframe[k], k)

  ...(etc)
Now, I've created a function to create the dataframes and insert them, and call that function in each afunction1/2/etc. per row, so each row is processed and inserted individually. So afunction1 will process the row list, then insert it in the dataframe, then attempt to insert that dataframe, and if it errors it will retry until success before moving on. So now it looks more like

Python code:
def worker(input):
  grab X chunks of data to work on
  for each chunk:
  

    afunction1(input) -> None (fully processes & outputs log)
    afunction2(input) ...
    ...
  
  return None

def main:
  chunksdata = worker(input)
  ...(etc)

Son of Thunderbeast fucked around with this message at 22:45 on Oct 2, 2023

Jose Cuervo
Aug 25, 2004
Writing a small Flask website that displays a bar chart. The bar chart displays the data for a single unit and there are 12 units. I want to easily navigate between the bar chart for each of the 12 units. I know I can build a form with a drop down selector and a submit button, and when I click the submit button the entire page will reload with the new data. I want to avoid reloading the entire page (and just update the bar chart) by using the drop down selector and fetch to accomplish this functionality.

What event do I need to listen out for with the drop down selector? I tried using 'click', but since you have to click once to bring up the list of options the fetch is being fired before a new unit has been selected (note that qrData is a variable which is declared earlier on the page, and I am trying to set it to the new data passed back by the "/qr_data" route).
JavaScript code:
    selectBtn.addEventListener('click',
                               function() {
                                 console.log('Clicked on the drop down');
                                 fetch("/qr_data", {method: "POST"})
                                    .then(newData => qrData=newData);
                               }
                              );
EDIT: Figured it out. I need to listen for the 'change' event.

Jose Cuervo fucked around with this message at 00:55 on Oct 3, 2023

duck monster
Dec 15, 2004

Folks. Don't Suppress(): errors. And dont except: pass them either.

Handle the drat things! Otherwise your just writing dangerous code.

duck monster
Dec 15, 2004

Jose Cuervo posted:

jablahblahscipr
[/code]

EDIT: Figured it out. I need to listen for the 'change' event.

Make life easier for yourself. Javascript is the hell dimension, but there are ways to make life less complicated: https://svelte.dev/
(If its just inhouse stuff and dont mind it looking like an IBM website, I solidly recomend the svelte carbon components from IBM)

Falcon2001
Oct 10, 2004

Eat your hamburgers, Apollo.
Pillbug

duck monster posted:

Folks. Don't Suppress(): errors. And dont except: pass them either.

Handle the drat things! Otherwise your just writing dangerous code.

There's plenty of times where you just want to say 'yeah there's no action to take here' and that pattern is fine. It's better than a bare except as well, since using suppress at least has you doing a specific exception clause.

Zugzwang
Jan 2, 2005

You have a kind of sick desperation in your laugh.


Ramrod XTreme
I'd only use it if I expected a specific kind of error to arise that I knew was okay to ignore.

One of the files I need to regularly read at work comes from a 3rd party and is essentially a giant LZMA2-compressed text file. Whenever I get to the end of it, it raises an EOFError due to a glitch in whatever they're using to compress it. (This error also shows up in 7-Zip; or rather, 7-Zip says "hey this file looks a bit odd" but still reads it okay.) I had to write a context manager specifically for ignoring EOFErrors in that dumb file type because otherwise my code would spend like 30 minutes rolling through it completely fine and then crash when it got to the very last line.

CarForumPoster
Jun 26, 2013

⚡POWER⚡
Selenium raises whenever an element isn’t present in a web page so try except NoSuchElementException is basically if/then.

It’s normal to verify something ISNT there by passing or suppressing.

QuarkJets
Sep 8, 2008

duck monster posted:

Folks. Don't Suppress(): errors. And dont except: pass them either.

Handle the drat things! Otherwise your just writing dangerous code.

Suppression just means "I expect this error, and I want to handle it by ignoring it." Sometimes that's okay

Consider a situation where you want to update an object from extracted values that are in a bunch of nested dictionaries, but if any of the keys are missing then you don't want to perform any updates. I'd argue that the best design here is to wrap the function call in suppress(KeyError).

Python code:
with contextlib.suppress(KeyError):
    new_values = some_function_that_may_raise_key_error(nested_dictionaries)
    some_object.update(new_values)
This has the desired behavior. This is equivalent to using schema to validate the nested dictionary's structure, so you could do that instead, but personally I think that using schema for this would be overkill. We could log a message in an except block here, but if those messages are pointless then we shouldn't be logging them.

QuarkJets
Sep 8, 2008

Import errors are another common reason to use suppression, for instance this is from scikit-learn:

Python code:
    n_jobs = 1
    with contextlib.suppress(ImportError):
        import joblib
        n_jobs = joblib.cpu_count()
I don't care if joblib is installed. If it is, great - use it. If it's not, no problem, move on

duck monster
Dec 15, 2004

*screams in programer documentation*

Why do libraries have such poo poo documentation?

Trying to implement Tortise ORM with Aerich migrations in Fastapi and holy gently caress is this painful. Theres a giant config object that is required that appears to be completely undocumented, and *all* possible configuration errors produce the same error with no hint on whats wrong. how to mark a table unmanaged so the migrations leaves it alone? Who the gently caress knows.

Come back Django. All is forgiven.

duck monster fucked around with this message at 06:51 on Oct 5, 2023

Hed
Mar 31, 2004

Fun Shoe
Python 3.12 is out and looks interesting. If you believe some benchmarks it looks like it could be 20-30% faster than 3.10 which I run a lot of.

Jose Cuervo
Aug 25, 2004
I want to make sure that a string that is passed in has the year-month format 'yyyy-mm'. So for example, '2022-09' would work or even '2022-9', but not '2022 09' or '22-09' etc. Should I be trying to use a regular expression for this?

spiritual bypass
Feb 19, 2008

Grimey Drawer
You could, but you could also split the string on - and parse the results into integers

e: woops, yeah, regex will validate that. Four digits, a -, then either 1 or 2 digits

CarForumPoster
Jun 26, 2013

⚡POWER⚡

Jose Cuervo posted:

I want to make sure that a string that is passed in has the year-month format 'yyyy-mm'. So for example, '2022-09' would work or even '2022-9', but not '2022 09' or '22-09' etc. Should I be trying to use a regular expression for this?

This seemed like a fun thing to pass to ChatGPT, so I asked for three ways it could be done because two seemed obvious: regex and datetime. It found a third and that other way ended up being the fastest (according to ChatGPT Advanced Data Analytics Plugin, I didnt test it)

code:
#Prompt: Give me three ways in python to make sure that a string that is passed in has the year-month format 'yyyy-mm'.  So for example, '2022-09' would work or even '2022-9', but not '2022 09' or '22-09' etc. 

import re
from datetime import datetime

# Method 1: Using Regular Expression
def is_valid_date1(date_str):
    return bool(re.fullmatch(r'\d{4}-\d{1,2}', date_str))

# Method 2: Using str.split() and integer conversion
def is_valid_date2(date_str):
    parts = date_str.split('-')
    return len(parts) == 2 and parts[0].isdigit() and len(parts[0]) == 4 and parts[1].isdigit()

# Method 3: Using datetime.strptime() for strict format matching
def is_valid_date3(date_str):
    try:
        datetime.strptime(date_str, '%Y-%m')
        return True
    except ValueError:
        return False

# Test the functions
test_strings = ['2022-09', '2022-9', '2022 09', '22-09']
results1 = [is_valid_date1(s) for s in test_strings]
results2 = [is_valid_date2(s) for s in test_strings]
results3 = [is_valid_date3(s) for s in test_strings]

results1, results2, results3
code:

# Prompt: Test which of the three functions is fastest in evaluating 100 example date strings. 

import timeit

# Generate 100 example date strings (50 valid and 50 invalid)
example_dates = ['2022-09', '1999-12', '2022 09', '22-09'] * 25

# Time each function
time1 = timeit.timeit("for s in example_dates: is_valid_date1(s)", globals=globals(), number=1000)
time2 = timeit.timeit("for s in example_dates: is_valid_date2(s)", globals=globals(), number=1000)
time3 = timeit.timeit("for s in example_dates: is_valid_date3(s)", globals=globals(), number=1000)

time1, time2, time3
RESULT
(0.1321420590000031, 0.04751532600000985, 0.7127733419999913)

DoctorTristan
Mar 11, 2006

I would look up into your lifeless eyes and wave, like this. Can you and your associates arrange that for me, Mr. Morden?
Looks like that third method (using str.split() and isdigit() ) will parse “2022-2022” as a valid date, and only the datetime.strptime() method will reject invalid months like “2022-17” so apples and oranges.

QuarkJets
Sep 8, 2008

Yeah I like how ChatGPT decided that there can't be more than 9999 years but more than 12 months is okay

Falcon2001
Oct 10, 2004

Eat your hamburgers, Apollo.
Pillbug

QuarkJets posted:

Yeah I like how ChatGPT decided that there can't be more than 9999 years but more than 12 months is okay


DoctorTristan posted:

Looks like that third method (using str.split() and isdigit() ) will parse “2022-2022” as a valid date, and only the datetime.strptime() method will reject invalid months like “2022-17” so apples and oranges.

This is, IMO, the biggest problem with ChatGPT and other things; they'll be wrong in ways that humans generally aren't, and generating code with it will cause all sorts of weird bugs, because it hasn't even attempted to work through the problem like a human would, it's just going to go 'yeah this is what it should look like'. It's like if you took advice from a guy who had read every stack overflow post, but hadn't written any actual code, and just wrote things down on paper and send them to you.

Not bad for basic boilerplate stuff where issues will be apparent, but every time I've asked it for regex it's been wrong, and it's hard to tell since regex is already an occult language.

Jose Cuervo
Aug 25, 2004
thought I must be missing some slick way to use regular expressions for this task, but I I think I will stick to checking the length of the string is 7 or 6. If the length is 7, then I will check for the 5th character being '-', the last two characters need to be one of 12 options ('01' through '12'), and that the first 4 four characters are a number between 2006 and 2023 (there is no data pre-2006). If the length is 6, then the only thing that changes is that the last character needs to be one of 9 options ('1' through '9').

Zugzwang
Jan 2, 2005

You have a kind of sick desperation in your laugh.


Ramrod XTreme
LLMs are useful when there's a lot of data ("how do I web scrape this page in Python") but decidedly less useful when there's not. :shrug:

It doesn't help at all that they don't actually understand anything, they just mush together stuff that is usually mushed together.

Zugzwang fucked around with this message at 19:59 on Oct 6, 2023

Falcon2001
Oct 10, 2004

Eat your hamburgers, Apollo.
Pillbug

Jose Cuervo posted:

thought I must be missing some slick way to use regular expressions for this task, but I I think I will stick to checking the length of the string is 7 or 6. If the length is 7, then I will check for the 5th character being '-', the last two characters need to be one of 12 options ('01' through '12'), and that the first 4 four characters are a number between 2006 and 2023 (there is no data pre-2006). If the length is 6, then the only thing that changes is that the last character needs to be one of 9 options ('1' through '9').

You could also try using https://www.programiz.com/python-programming/datetime/strptime to brute force it and do error checking to see if you've passed in a bad date. At least that way you're using a consistent, proven method for date validation instead of rolling your own.

QuarkJets
Sep 8, 2008

Yeah datetime.strptime does most of that poo poo for you, I don't remember if it needs to be given different character codes for 4-digit vs 2-digit years but that's the much simpler implementation. Use them standard tools

ComradePyro
Oct 6, 2009

Zugzwang posted:

It doesn't help at all that they don't actually understand anything, they just mush together stuff that is usually mushed together.

succinct description of most reddit comments

Data Graham
Dec 28, 2009

📈📊🍪😋



I was gonna suggest strptime but wasn’t the question about the fastest method, strptime being one possible option? (And the slowest)

Falcon2001
Oct 10, 2004

Eat your hamburgers, Apollo.
Pillbug

Data Graham posted:

I was gonna suggest strptime but wasn’t the question about the fastest method, strptime being one possible option? (And the slowest)

The original question didn't require fastest, that was just a followup note.


Jose Cuervo posted:

I want to make sure that a string that is passed in has the year-month format 'yyyy-mm'. So for example, '2022-09' would work or even '2022-9', but not '2022 09' or '22-09' etc. Should I be trying to use a regular expression for this?

Regex would probably be fastest, but like...this isn't exactly a hyper expensive thing to check unless you're doing this millions of times a second or something. I dunno the workflow but it woudl be an insane setup to revalidate something like that so frequently.

Edit: wow I'm an idiot, it's literally in the timeit results from the other goon. Teach me to post while working. Still 6x increase in time is probably not meaningful for something so small.

Falcon2001 fucked around with this message at 23:40 on Oct 6, 2023

Zugzwang
Jan 2, 2005

You have a kind of sick desperation in your laugh.


Ramrod XTreme

ComradePyro posted:

succinct description of most reddit comments
:hmmyes:

QuarkJets
Sep 8, 2008

Yeah I am not going to worry about the efficiency of strptime until I've seen proof that it's bogging down my software, often that half-millisecond is not going to matter and if it does then I'm probably not going to use option 1 or 2 either

QuarkJets fucked around with this message at 04:47 on Oct 7, 2023

KICK BAMA KICK
Mar 2, 2009

Do you guys have any tips for using Python to do insane amounts of crime
https://x.com/molly0xFFF/status/1710718416724595187?s=20

Macichne Leainig
Jul 26, 2012

by VG
Yeah, don't get caught like that fuckin' assclown

Zugzwang
Jan 2, 2005

You have a kind of sick desperation in your laugh.


Ramrod XTreme
I am a mediocre programmer and only know how to commit sane amounts of crime

DoctorTristan
Mar 11, 2006

I would look up into your lifeless eyes and wave, like this. Can you and your associates arrange that for me, Mr. Morden?

KICK BAMA KICK posted:

Do you guys have any tips for using Python to do insane amounts of crime
https://x.com/molly0xFFF/status/1710718416724595187?s=20

Obfuscate better than def do_crimes()

Adbot
ADBOT LOVES YOU

Presto
Nov 22, 2002

Keep calm and Harry on.
from crimes import financial_fraud

  • 1
  • 2
  • 3
  • 4
  • 5
  • Post
  • Reply