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
Hed
Mar 31, 2004

Fun Shoe
This is probably premature optimization but the issue I feel with Lambda is that for scrapers that pause/wait to be nice, it’s a lot of milliseconds Nooping whereas if I run it on my hardware I get the benefits of statistical multiplexing. Writing that out though it’s probably something to worry about another day.

Still, as far as having tasks get serialized parameters in and report back I’m looking for patterns or best practices. Something like Two Scoops that has a bunch of good patterns is pretty much “sometimes we use Lambda but it’s hard to debug” and that’s it.

Adbot
ADBOT LOVES YOU

cinci zoo sniper
Mar 15, 2013




The decision for you to make basically is if you want to wait for a response from the job, or for a callback (signal in Django parlance). Which one to use depends on the specifics of application architecture.

For your job configuration just have like a pydantic data class that gets serialised to JSON via dictionaries. The configuration should include both application tasks and logistics around logging, storage, and responses.

CarForumPoster
Jun 26, 2013

⚡POWER⚡

Hed posted:

I've got a Django site that wants to run tasks and I could use celery/redis-queue/whatever but these jobs are calling containers that are also Python but don't know about Django. So I want to dispatch a task from Django to one of these artifacts and give it configuration. Need something to spawn these (could be containers, could be FaaS) and then when they're done, report back with status and data. Logging would also be great.

Does anyone have strategies for this? I feel like I'm circling around something but need a topic keyword to research.


Hed posted:

Sure! These tasks call a job to go scrape a forum, or thread, or threadpage. So the container would start up, read configuration (from injected environment, injected config file, http call??), then use that to call functions in the container, do the work, then eventually the work needs to go to S3, and status needs to get back to the Django site somehow. Logs can go to anywhere, I’d just like to be able to look at them when things go wrong.

Hed posted:

This is probably premature optimization but the issue I feel with Lambda is that for scrapers that pause/wait to be nice, it’s a lot of milliseconds Nooping whereas if I run it on my hardware I get the benefits of statistical multiplexing. Writing that out though it’s probably something to worry about another day.

Still, as far as having tasks get serialized parameters in and report back I’m looking for patterns or best practices. Something like Two Scoops that has a bunch of good patterns is pretty much “sometimes we use Lambda but it’s hard to debug” and that’s it.

I still say +1 for AWS Lambda. If you need to not pay for the wait time, AWS step functions may be something you want, this would let you create a list of scrapes to do that limits concurrency and can wait. If youre behind a login just pass the cookie. Not sure what Two Scoops is.

Debugging in development with Lambdas is pretty easy if you're using the SAM CLI because you can have a docker container that behaves "just like" the deployed environment. You can time.sleep(900) and CLI in, access the python REPL, etc. Debugging in prod is another story. IDK what best practices are but I use a watchdog to fetch logs at an interval and put them where I want.

Also IME getting Celery/Redis working with my Django or Flask apps has ALWAYS been plagued by gotchas for me. With a lambda function deployed as a docker container via SAM CLI I can ship a big rear end 3GB docker image with my binaries and poo poo all built in and it JUST WORKSTM

CarForumPoster fucked around with this message at 16:20 on Feb 10, 2022

Wallet
Jun 19, 2006

cinci zoo sniper posted:

For your job configuration just have like a pydantic data class that gets serialised to JSON via dictionaries. The configuration should include both application tasks and logistics around logging, storage, and responses.

Unless I'm misunderstanding the question you could also just use celery to create jobs and have a celery server that runs them with a queue. Having it actually spawn a server to run the job seems like unnecessary complexity. I'm assuming you want to store the results somewhere in a database or whatever anyway so why not just store information about the run in the same place?

D34THROW
Jan 29, 2012

RETAIL RETAIL LISTEN TO ME BITCH ABOUT RETAIL
:rant:

QuarkJets posted:

Eep! range is a built-in, you should use a different variable name there

:doh: Yes, yes, it is and I was trying to coerce a way to use it for what I needed before I discovered arange()...so you'd think I remembered using range as a variable range was verboten. Thank you for pointing that out.

Popete
Oct 6, 2009

This will make sure you don't suggest to the KDz
That he should grow greens instead of crushing on MCs

Grimey Drawer

QuarkJets posted:

What you're looking for is a class attribute, but what you're describing (a module secretly modifying shared data being used by another module, but without being called directly?) is frustrating to debug and has poor readability. You should define functions that mutate data in a clear and concise way. Have one of these modules pass an instance of the class to the other module for mutation

Maybe I can clarify what I'm trying to do. I have a Python daemon running in the background, it is monitoring system temperatures and updating a dictionary (part of an imported class) with fault status if the temps ever go out of range. I have a separate app that can be run by a user that I want to check the status of these temperature faults being managed by the background daemon. This requires some sort of IPC but I'm having trouble thinking of the best way to do this in Python. Ideally I could shared the object being managed by the daemon with the fault viewing app.

D34THROW
Jan 29, 2012

RETAIL RETAIL LISTEN TO ME BITCH ABOUT RETAIL
:rant:
Update on the prettification - it's no longer done by a separate class but by the Calculator class that is the root object used to calculate poo poo. I'm rather proud of the implementation here - the idea being that the route for a report will loop through the materials dict, then the size dicts contained within, to generate the pretty data to spit into a table.

Python code:
class Calculator():
    def __init__(self): self.materials = {}

    ...

    def add_to_materials(self, item: str, qty: int, size: str = ' '):
        if type(size) != str: size = str(size)
        if qty > 0:
            if item not in self.materials.keys():
                self.materials[item] = {}
                self.materials[item][size] = qty
            else:
                if size not in self.materials[item].keys():
                    self.materials[item][size] = qty
                else:
                    self.materials[item][size] += qty
    
    def print_materials(self):
        for item, s in self.materials.items():
            print(f'{item.ljust(40)}')
            for size, qty in self.materials[item].items():
                if size == ' ':
                    print(f'{str(qty).rjust(6)}')
                else:
                    print(f'  {str(qty).rjust(6)} @ {size.rjust(10)}')

    ...

Output for a 37x63 window is exactly as expected given inputs.
code:
>>> from app.calculators.stormprot import *; foo = StormPanelOpening(37, 63); foo.print_materials()
PANELMATE MALE
    14
PANELMATE CAP
    14
STORM PANEL .050 FULL
     3 @         67

D34THROW fucked around with this message at 19:37 on Feb 10, 2022

Hed
Mar 31, 2004

Fun Shoe
Thanks all for the help.

CarForumPoster posted:

I still say +1 for AWS Lambda. If you need to not pay for the wait time, AWS step functions may be something you want, this would let you create a list of scrapes to do that limits concurrency and can wait. If youre behind a login just pass the cookie. Not sure what Two Scoops is.

Debugging in development with Lambdas is pretty easy if you're using the SAM CLI because you can have a docker container that behaves "just like" the deployed environment. You can time.sleep(900) and CLI in, access the python REPL, etc. Debugging in prod is another story. IDK what best practices are but I use a watchdog to fetch logs at an interval and put them where I want.

Also IME getting Celery/Redis working with my Django or Flask apps has ALWAYS been plagued by gotchas for me. With a lambda function deployed as a docker container via SAM CLI I can ship a big rear end 3GB docker image with my binaries and poo poo all built in and it JUST WORKSTM

So do you have the task just do an HTTP callback into Django/Flask with results? If that fails does it just repeat the work?


cinci zoo sniper posted:

For your job configuration just have like a pydantic data class that gets serialised to JSON via dictionaries. The configuration should include both application tasks and logistics around logging, storage, and responses.

That makes sense, I've been using the schnizz out of data classes -> JSON for the scraping results anyway so this is a natural extension. Pydantic looks great.

Hed fucked around with this message at 21:55 on Feb 10, 2022

CarForumPoster
Jun 26, 2013

⚡POWER⚡

Hed posted:

Thanks all for the help.

So do you have the task just do an HTTP callback into Django/Flask with results? If that fails does it just repeat the work?

It depends, you can trigger the Lambda synchronously via API gateway or using boto3 via django. If you know to absolute certainty that you're gonna get a "quick" response from Lambda, this is a very easy way to do it.

Since we're talking web scraper, this probably isn't your scenario. The first way that comes to mind would be to trigger (invoke()) the lambda "async" via boto3, which will give you an ID for the lambda execution. Then poll the status of the Lambda function on some interval. If complete, get the data from wherever the Lambda put it. If it fails, handle that as desired.

Boto3 docs
https://boto3.amazonaws.com/v1/documentation/api/latest/reference/services/lambda.html#Lambda.Client.invoke

CarForumPoster fucked around with this message at 22:05 on Feb 10, 2022

PIZZA.BAT
Nov 12, 2016


:cheers:


is there a python library that will wrap socket and just read until it encounters an endline? i've spent all day debugging and hacking and realized that it all boiled down to makefile/recv being unreliable. i can just write it myself but with all the libraries that exist in this ecosystem to make your life easier i'm really surprised that i can't find something that does this

cinci zoo sniper
Mar 15, 2013




PIZZA.BAT posted:

is there a python library that will wrap socket and just read until it encounters an endline? i've spent all day debugging and hacking and realized that it all boiled down to makefile/recv being unreliable. i can just write it myself but with all the libraries that exist in this ecosystem to make your life easier i'm really surprised that i can't find something that does this

I would do MSG_PEEK and check for EOL, to be frank.

12 rats tied together
Sep 7, 2006

id use twisted, but it does (a lot) more than that, and its kinda heavyweight

PIZZA.BAT
Nov 12, 2016


:cheers:


yeah i think i'm spoiled by java's readline functionality built into the standard library. it just seems really weird that a language as mature as python doesn't have something that basic

cinci zoo sniper
Mar 15, 2013




PIZZA.BAT posted:

yeah i think i'm spoiled by java's readline functionality built into the standard library. it just seems really weird that a language as mature as python doesn't have something that basic

I think it's safe to bet that 99% of Python developers have never had to touch something as low level as a socket.

Hed
Mar 31, 2004

Fun Shoe
I feel like you could just use or override some stuff in telnetlib in the std lib.

cinci zoo sniper posted:

I think it's safe to bet that 99% of Python developers have never had to touch something as low level as a socket.

Probably true. I’ve done a bunch of socket programming in Python to get the FSM and primitives right. Used to maintain a ton of line-oriented query servers that replaced some PERL ones, though.

Dawncloack
Nov 26, 2007
ECKS DEE!
Nap Ghost
I have to backfill information into an SQL database, and I am writing a python script for it.

I depend on some other piece of software to send unix timestamps to (and other info) and then get the info to backfill from it.
This program offers me two options: To get an old date and give me the data from that date or ask for real time information and get this exact moment's data.

I have a problem tho: The real time information has two decimals of precision that the old info does not.

What would be the easiest way to change my system's time a buncha times so that, combined with the other info, I get the better precision ?

Thanks!

edit: I am thinking it might be easier to change the information I feed the program and pretend it's all from right now.

Dawncloack fucked around with this message at 20:20 on Feb 12, 2022

Falcon2001
Oct 10, 2004

Eat your hamburgers, Apollo.
Pillbug

Dawncloack posted:

I have to backfill information into an SQL database, and I am writing a python script for it.

I depend on some other piece of software to send unix timestamps to (and other info) and then get the info to backfill from it.
This program offers me two options: To get an old date and give me the data from that date or ask for real time information and get this exact moment's data.

I have a problem tho: The real time information has two decimals of precision that the old info does not.

What would be the easiest way to change my system's time a buncha times so that, combined with the other info, I get the better precision ?

Thanks!

edit: I am thinking it might be easier to change the information I feed the program and pretend it's all from right now.

Can you just modify the data you get to or from that program? Because modifying timestamps to add precision (even fake precision) is probably a lot easier than figuring out a way to muck with your system time programmatically, although I'm sure there's a way to do it.

Maybe give some examples of the input/output data?

Falcon2001 fucked around with this message at 03:27 on Feb 13, 2022

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?

Dawncloack posted:

I have to backfill information into an SQL database, and I am writing a python script for it.

I depend on some other piece of software to send unix timestamps to (and other info) and then get the info to backfill from it.
This program offers me two options: To get an old date and give me the data from that date or ask for real time information and get this exact moment's data.

I have a problem tho: The real time information has two decimals of precision that the old info does not.

What would be the easiest way to change my system's time a buncha times so that, combined with the other info, I get the better precision ?

Thanks!

edit: I am thinking it might be easier to change the information I feed the program and pretend it's all from right now.

I'm having a hard time believing that the data retrieval works in the way you describe, or that what you're attempting to do would even work, let alone whether it's a good idea.

Before you go creating your very own entry for the coding horrors thread, a few questions.

From what you've described like the system offers two interfaces to the data - get_historical_data(date) and get_realtime_data() (or similar). To me that screams that the system contains two data storage components - a real-time stream or queue and a data store populated from that stream/queue - and that get_realtime_data() simply retrieves the latest data from the stream. If that's the case then changing your system time won't get you the data you want (in addition to being horrific behaviour in and of itself).

Similarly, the most likely (to me) explanation for the difference in precision between the two methods is that the system has an archive data store that was improperly set up and the data gets truncated on storage. If that's the case there's nothing you can do to recover the lost precision.

Of course it's possible that get_realtime_data() is for some extremely hosed up reason getting your system time and using that to query the archive and that the truncation in the other method is happening in the interface instead of the actual storage, but all of that would require some truly galaxy-brained programming from whoever implemented the interface - so much so that I would seriously question whether any of the interfaces were even retrieving the correct data in the first place.

So have you verified that changing the system time in the call to get_latest_data() actually gets you the data you want, and not (eg) just the latest data with the timestamp changed?

Pyromancer
Apr 29, 2011

This man must look upon the fire, smell of it, warm his hands by it, stare into its heart
I'm trying a simple custom authorizer in AWS Lambda where as the first step I validate the token signature with pyjwt and cryptography.
Much to my surprise cryptography fails to initialize about 5% of the time, seemingly random, no errors, no nothing; signature validation just goes into timeout even if it's set as long as 30 seconds. That instance of lambda stays completely broken and unable to handle requests; until a new instance is created and that one works fine(95% of the time). How can I find out what is going on there?

CarForumPoster
Jun 26, 2013

⚡POWER⚡

Pyromancer posted:

I'm trying a simple custom authorizer in AWS Lambda where as the first step I validate the token signature with pyjwt and cryptography.
Much to my surprise cryptography fails to initialize about 5% of the time, seemingly random, no errors, no nothing; signature validation just goes into timeout even if it's set as long as 30 seconds. That instance of lambda stays completely broken and unable to handle requests; until a new instance is created and that one works fine(95% of the time). How can I find out what is going on there?

It's been a long while since I made an authorizer for a Lambda, so IDK if there's a gotcha here but did you make a logging stream at the debug level to hit cloudwatch logs? If yes, what do the logs say?

Pyromancer
Apr 29, 2011

This man must look upon the fire, smell of it, warm his hands by it, stare into its heart

CarForumPoster posted:

It's been a long while since I made an authorizer for a Lambda, so IDK if there's a gotcha here but did you make a logging stream at the debug level to hit cloudwatch logs? If yes, what do the logs say?

Nothing too useful, from what I see it loads JWK from the url so it's not a network timeout, but hits a wall when trying to turn JWK into a public key object. It's also the same JWK in all tests so I have no idea why it usually loads but sometimes not.
For subsequent calls of a broken lambda instance memory usage drops from 55 to 23 MB, unlike the normally running instances staying at 55, I don't know what that hints at.

CarForumPoster
Jun 26, 2013

⚡POWER⚡

Pyromancer posted:

Nothing too useful, from what I see it loads JWK from the url so it's not a network timeout, but hits a wall when trying to turn JWK into a public key object. It's also the same JWK in all tests so I have no idea why it usually loads but sometimes not.
For subsequent calls of a broken lambda instance memory usage drops from 55 to 23 MB, unlike the normally running instances staying at 55, I don't know what that hints at.

Spitballing ideas here but...

First thing I check when getting anomalous Lambda issues on a new deployment is whether it can access all the pieces of the system. IAM, security groups, networking, etc. For example if you need to access something for which you have two security groups, but only one of the SGs has a proper connection to the resource, that can cause issues.

I deploy Lambdas with AWS SAM, which lets me remote into the "Lambda-like" docker environment when testing locally. Apparently SAM does support authorizers, so you may want to try running your API locally and hit the authorizer locally to see if you can reproduce.

Docs:
https://docs.aws.amazon.com/serverless-application-model/latest/developerguide/serverless-controlling-access-to-apis-lambda-authorizer.html

D34THROW
Jan 29, 2012

RETAIL RETAIL LISTEN TO ME BITCH ABOUT RETAIL
:rant:
Having a little trouble with a Flask WTForm FieldList(FormField()) combined with a SelectField() in the nested form. Everything renders perfectly fine - with blank SelectFields - until I start trying to dynamically populate the SelectFields from DB lookups. See attached code, error thrown is AttributeError: 'FieldList' object has no attribute 'top_attachment' at the ***. WTForms documentation isn't really helping me much with this particular issue; the docs show a SelectField being used but it is populated while populating the form, not at runtime as mine is.

forms.py code:
Python code:
class StormPanelForm(ReportForm):
    lines = FieldList(FormField(StormPanelLineItemForm), min_entries=1)

class StormPanelLineItemForm(Form):
    width = IntegerField("Opening Width", validators=[DataRequired()])
    height = IntegerField("Opening Height", validators=[DataRequired()])
    trapped = RadioField("Trapped", choices=[(0, 'No'), (1, 'Yes')], default=0)
    removable = RadioField("Removable", 
        choices=[(0, 'No'), (1, 'Yes')], default=0)
    direction = RadioField("Direction", choices=[(1, 'Vertical'),
        (2, 'Horizontal')], default=1)
    top_attachment = SelectField('Top Attachment', coerce=int)
    bottom_attachment = SelectField('Bottom Attachment', coerce=int)
    buildout = SelectField('Buildout', coerce=int)
    clear_panels = IntegerField("# of Clear Panels", default=0)
And the routes.py code:
Python code:
@bp.route('/stormpanel', methods=GET_POST)
def stormpanel():
    title = f'{app.config["TITLE_BASE"]} Storm Panel Calculator'
    mounts = db.session.query(StormPanelMounting).order_by(StormPanelMounting.id) 
    mount_list = [(m.id, m.name) for m in mounts]
    buildouts = db.session.query(StormProtBuildout).order_by(StormProtBuildout.id)
    buildout_list = [(b.id, b.name) for b in buildouts]
    form = StormPanelForm()
    form.lines.top_attachment.choices = mount_list ***
    form.lines.bottom_attachment.choices = mount_list
    form.lines.buildout.choices = buildout_list

    return render_template('stormpanel.html', title=title, form=form)

fisting by many
Dec 25, 2009



Pyromancer posted:

I'm trying a simple custom authorizer in AWS Lambda where as the first step I validate the token signature with pyjwt and cryptography.
Much to my surprise cryptography fails to initialize about 5% of the time, seemingly random, no errors, no nothing; signature validation just goes into timeout even if it's set as long as 30 seconds. That instance of lambda stays completely broken and unable to handle requests; until a new instance is created and that one works fine(95% of the time). How can I find out what is going on there?

Which version of cryptography are you using? I had a similar problem where an old version (like, 4.x) would occasionally take incredibly long (minutes+) to initialize, upgrading to 36.x solved it.

PierreTheMime
Dec 9, 2004

Hero of hormagaunts everywhere!
Buglord
Whats the “best” way using boto3 to read S3 content into a stream that can be used in in a single POST request? I’d prefer to stick with Lambda “native” libraries if possible but it’s not critical.

CarForumPoster
Jun 26, 2013

⚡POWER⚡

PierreTheMime posted:

Whats the “best” way using boto3 to read S3 content into a stream that can be used in in a single POST request? I’d prefer to stick with Lambda “native” libraries if possible but it’s not critical.

It'd be like 3 lines of code if you use boto3+requests.

Get the file object as bytes via boto3, transmit file object using requests.

PierreTheMime
Dec 9, 2004

Hero of hormagaunts everywhere!
Buglord

CarForumPoster posted:

It'd be like 3 lines of code if you use boto3+requests.

Get the file object as bytes via boto3, transmit file object using requests.

To clarify, I’m looking to post like 10-20GB of data so I’m looking to stream it. Loading the whole file into memory isn’t going to be feasible in Lambda.

Bad Munki
Nov 4, 2008

We're all mad here.


If you’re using lambda (and, say, api gateway) and hoping to stream that content back to a client, it won’t work the way you want, lambda returns its response en bloc, unless they’ve changed something fundamental about it since I last had to deal with this.

You said in a single POST request, so I understand you’re the one making the request as a client, not fielding it as a server, but just in case, be aware of that limitation.

None of what I said actually pertains to streaming a file from S3, though. But you said “lambda” and “stream” and it caught my attention.

Bad Munki fucked around with this message at 14:51 on Feb 15, 2022

PierreTheMime
Dec 9, 2004

Hero of hormagaunts everywhere!
Buglord

Bad Munki posted:

If you’re using lambda (and, say, api gateway) and hoping to stream that content back to a client, it won’t work the way you want, lambda returns its response en bloc, unless they’ve changed something fundamental about it since I last had to deal with this.

You said in a single POST request, so I understand you’re the one making the request as a client, not fielding it as a server, but just in case, be aware of that limitation.

None of what I said actually pertains to streaming a file from S3, though. But you said “lambda” and “stream” and it caught my attention.

I appreciate you checking. I'm invoking the an AWS Lambda function through Step Functions and using it to push data via API (currently using urllib3 since it's baked into the image and simple enough). The Lambda return value is going to be discarded.

CarForumPoster
Jun 26, 2013

⚡POWER⚡

PierreTheMime posted:

To clarify, I’m looking to post like 10-20GB of data so I’m looking to stream it. Loading the whole file into memory isn’t going to be feasible in Lambda.


PierreTheMime posted:

I appreciate you checking. I'm invoking the an AWS Lambda function through Step Functions and using it to push data via API (currently using urllib3 since it's baked into the image and simple enough). The Lambda return value is going to be discarded.

Ohhh. So your step function does stuff and among that stuff is a step where a Lambda is going to POST a large file that it retrieves from S3. You can stream out via urllib and want to know how to get the file "chunks" from S3 to stream.

I haven't done this but I think you'd get() [Docs], then take what's in the StreamingBody and deliver it to your urllib object for streaming out.

Alternatively, I havent tried it but this exists: https://github.com/RaRe-Technologies/smart_open

QuarkJets
Sep 8, 2008

smart_open is the smart way to get a byte stream to an object on s3, I don't know how well you can stream it out with a lambda but may as well give it a shot. For full-file reading it really is as easy to use as it sounds, smart_open.open(s3_url, 'rb') will give you a byte stream for the s3 object, I just haven't tried streaming something out like you're trying to do

D34THROW
Jan 29, 2012

RETAIL RETAIL LISTEN TO ME BITCH ABOUT RETAIL
:rant:
I got it. Had to loop through the FieldList(FormField()) controls and go from there based on the .name attribute.

Python code:
for item in form.lines:
    for widget in item:
        widget_name = widget.name.split('-')[2]
        if widget_name == "top_attachment":
            widget.choices = mount_list
        elif widget_name == "bottom_attachment":
            widget.choices = mount_list
        elif widget_name == "buildout":
            widget.choices = buildout_list
Now for the added fun of trying to figure out how to use AJAX to insert a child field without refreshing the whole loving page. Top answer on Google is decidedly unhelpful, the poster had the same question and answered it themselves without posting the actual damned solution.

credburn
Jun 22, 2016
A tangled skein of bad opinions, the hottest takes, and the the world's most misinformed nonsense. Do not engage with me, it's useless, and better yet, put me on ignore.
Hey gang, I'm new at Python and trudging through an online course in it in pursuit of a degree in Data Analytics. I'm having an awful time trying to get a probably pretty simple bit of code to work correctly; is this a place I could periodically post code and just ask if people could look at it and tell me what I'm doing wrong?

I've been at this for hours and am exhausted. Since this is an online college, I can't exactly just raise my hand and ask; I have to schedule a thirty minute meeting days in advance and the kinds of questions I have aren't 30 minute long questions :\

a dingus
Mar 22, 2008

Rhetorical questions only
Fun Shoe
yeah just post it

Phobeste
Apr 9, 2006

never, like, count out Touchdown Tom, man
That’s basically exactly what the threads for, hopefully the newbies here get something out of the pros explaining not only the how but the why

credburn
Jun 22, 2016
A tangled skein of bad opinions, the hottest takes, and the the world's most misinformed nonsense. Do not engage with me, it's useless, and better yet, put me on ignore.
Alright, here is my code:

code:
def get_quotient(user_num, div_num):
    quotient = user_num // div_num
    return quotient

if __name__ == '__main__':
    try:
        user_num = input()
        if int(user_num) == False:
            user_num = str(user_num)
            raise ValueError()
        user_num = int(user_num)
        div_num = input()
        if int(div_num) == False:
            div_num = str(div_num)
            raise ValueError()
        div_num = int(div_num)
        if div_num == 0:
            raise ZeroDivisionError()
        quotient = get_quotient(user_num, div_num)
        print(quotient)
    except ValueError:
        print('Input Exception: invalid literal for int() with base 10: ' + "'" + user_num + "'")
    except ZeroDivisionError:
        print('Zero Division Exception: integer division or modulo by zero')
My task is to write a program that will take two inputs and divide the first by the second. That's easy, and the program functions as intended. The second part of the task is I need to create exception handlers for when non-integers are entered or when trying to divide by zero.

There's a couple issues I'm having. The first is the ZeroDivisionError; it seems to believe if 0 is entered as the div_num, then it's not an integer. I thought by adding an int(0) to it, it would help, but everything I try to do with it, it seems to just think I'm trying to say "none" or "false" but I really just mean the integer 0.

So my initial question, how can I write: if div_num == 0: and make it think I'm asking about an integer and not a boolean thing?

Defeatist Elitist
Jun 17, 2012

I've got a carbon fixation.

Maybe I'm missing something very simple but wouldn't

code:

if int(div_num) == False:
            div_num = str(div_num)
            raise ValueError()

cause any input of 0 to be turned into a string, then raise a ValueError?

What is this statement trying to do?

edit: phone posting from the bus so let me know if this is unclear or totally wrong

edit2: I assume you are trying to check if div_num is an integer or can be an integer here, but it doesn't work the way you want it to. If you pass an arbitrary non number string to int() it will give a ValueError, not return False. Meanwhile, 0 is a falsey value so int(0) will == False.

Defeatist Elitist fucked around with this message at 02:25 on Feb 18, 2022

credburn
Jun 22, 2016
A tangled skein of bad opinions, the hottest takes, and the the world's most misinformed nonsense. Do not engage with me, it's useless, and better yet, put me on ignore.

Defeatist Elitist posted:

Maybe I'm missing something very simple but wouldn't

code:
if int(div_num) == False:
            div_num = str(div_num)
            raise ValueError()
cause any input of 0 to be turned into a string, then raise a ValueError?

What is this statement trying to do?

edit: phone posting from the bus so let me know if this is unclear or totally wrong

edit2: I assume you are trying to check if div_num is an integer or can be an integer here, but it doesn't work the way you want it to. If you pass an arbitrary non number string to int() it will give a ValueError, not return False. Meanwhile, 0 is a falsey value so int(0) will == False.

That block of code is meant to see if div_num is an integer, and if it is not, then it converts whatever it is to a string so that I can easily concatenate it into the ValueError exception. It works if the number is anything but 0.

But the problem is, if it's a 0, then... everything goes nuts. How else can I check if something is both an integer and 0?

Defeatist Elitist
Jun 17, 2012

I've got a carbon fixation.

credburn posted:

That block of code is meant to see if div_num is an integer, and if it is not, then it converts it to a string so that I can easily concatenate it into the ValueError exception.

But the problem is, if it's a 0, then... everything goes nuts. How else can I check if something is both an integer and 0?

If it's a 0 then it will == False. If it's not an integerable number this won't even catch it the way you want to. Calling int() on, say, 'cool' will already throw a ValueError, it won't make it to your raise statement.

edit: broadly I don't think this is the best way to construct what you are making, but I'm not sure exactly what the assignment calls for. Are you specifically supposed to raise your own exceptions? If so, is there a reason the expeditions aren't being raised in the function itself? When you say non-ints should throw a ValueError, do you mean anything that is not literally an int already (including string representations of an int, floats, etc)? Do you mean anything that can't be cast to an int? Or do you mean anything that is not equivalent to an int?

Defeatist Elitist fucked around with this message at 02:49 on Feb 18, 2022

Adbot
ADBOT LOVES YOU

credburn
Jun 22, 2016
A tangled skein of bad opinions, the hottest takes, and the the world's most misinformed nonsense. Do not engage with me, it's useless, and better yet, put me on ignore.
I think where I'm most confused is that I want to at the same time check to see if the variable is an integer, and also if it is 0. If the value was 7, that can just be done with int(var), but because it's 0, it crashes. Or just does things I'm not intending.

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