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
Macichne Leainig
Jul 26, 2012

by VG

John DiFool posted:

In 2006 I made ~30k on a 6-month *internship*. So ~60k a year. ~85k in 2022 dollars. You are absolutely shafting your interns.

Here's an idea, if you don't want to do the entry-level Python job for purportedly less money than the internship you had, then don't!

And let people make their own decisions :)

Adbot
ADBOT LOVES YOU

Jabor
Jul 16, 2010

#1 Loser at SpaceChem
I think it's pretty reasonable to call out that something might be significantly below-market - often the sort of new-to-the-industry person who's the focus of that ad doesn't have a good idea of what typical compensation looks like.

If it is actually good compensation for the sort of applicant being targeted, then it's not like it's hurting anybody if that applicant has a look around and realises what typical market rates are first.

John DiFool
Aug 28, 2013

Macichne Leainig posted:

Here's an idea, if you don't want to do the entry-level Python job for purportedly less money than the internship you had, then don't!

Nah, I’m going to call out people who are paying way below market. Rather help out those starting out who may not know better.

Employers who talk about high expectations while offering low wages are almost universally exploiting workers.

I didn’t live in a particularly high COL area either.

Hopefully people considering this position will see this exchange and wonder why they’d want to work for someone that severely undervalues their time and labor.

Macichne Leainig posted:

And let people make their own decisions :)

Maybe you should let me speak so they have more data to make their own decisions instead of being a passive aggressive prick.

CarForumPoster
Jun 26, 2013

⚡POWER⚡
I have Pave.com benchmarking, have hired multiple interns and cited paying above market for a specific well known employer but otoh you did have one job more than a decade ago so maybe I’ll just ignore all that real data I have and listen to some goon.

John DiFool
Aug 28, 2013

CarForumPoster posted:

I have Pave.com benchmarking, have hired multiple interns and cited paying above market for a specific well known employer but otoh you did have one job more than a decade ago so maybe I’ll just ignore all that real data I have and listen to some goon.

Congrats on the cheap labor my dude.

John DiFool
Aug 28, 2013

It’s funny how quickly hiring managers get in a huff if you dare suggest they might be paying poo poo wages.

CarForumPoster
Jun 26, 2013

⚡POWER⚡
Yea it's weird how people acting ethically and transparently get in a huff when a belligerent moron accuses them of unethical behavior.

Falcon2001
Oct 10, 2004

Eat your hamburgers, Apollo.
Pillbug
Is there a 'fight about how capitalism sucks for everyone' thread y'all could go fight in instead?

Bad Munki
Nov 4, 2008

We're all mad here.


Falcon2001 posted:

Is there a 'fight about how capitalism sucks for everyone' thread y'all could go fight in instead?

Yeah but there’s a global market interpretation lock

QuarkJets
Sep 8, 2008

Macichne Leainig posted:

Here's an idea, if you don't want to do the entry-level Python job for purportedly less money than the internship you had, then don't!

And let people make their own decisions :)

Is posting in the thread somehow not letting people make their own decisions?

IMO if it's okay to post a job posting then it's also ok for people to remark on it in whatever way they want.

Jose Cuervo
Aug 25, 2004
I have a large amount of blood glucose time series data from here: https://public.jaeb.org/datasets/diabetes. Each row of the time series data has at least 4 columns - an identifier of which trial the data belongs to, an identifier of which subject from the trial the data belongs to, the date and time of the blood glucose, and the actual value of the blood glucose, and conservatively there are over 20 million rows.

Given a list of subjects and a date time for each subject, I would like to be able to quickly obtain the next 2 hours of blood glucose data for each of those subjects, and I will be performing this query repeatedly.

I have no real experience with databases, but given the size of the data it seems like it would be best to store this data in a database and then run queries to extract the data I want.

Is a Sqlite database with a single table the best way to store this data given the queries I want to run? The single table would have four columns (trial ID, subject ID, date time, and blood glucose value).

Twerk from Home
Jan 17, 2009

This avatar brought to you by the 'save our dead gay forums' foundation.

Jose Cuervo posted:

I have a large amount of blood glucose time series data from here: https://public.jaeb.org/datasets/diabetes. Each row of the time series data has at least 4 columns - an identifier of which trial the data belongs to, an identifier of which subject from the trial the data belongs to, the date and time of the blood glucose, and the actual value of the blood glucose, and conservatively there are over 20 million rows.

Given a list of subjects and a date time for each subject, I would like to be able to quickly obtain the next 2 hours of blood glucose data for each of those subjects, and I will be performing this query repeatedly.

I have no real experience with databases, but given the size of the data it seems like it would be best to store this data in a database and then run queries to extract the data I want.

Is a Sqlite database with a single table the best way to store this data given the queries I want to run? The single table would have four columns (trial ID, subject ID, date time, and blood glucose value).

SQLite with a multi-column index on subject id and timestamp should work well. If you think you'll need to query by timestamp only but not subject only, reverse that order.

https://use-the-index-luke.com/sql/where-clause/the-equals-operator/concatenated-keys

QuarkJets
Sep 8, 2008

Jose Cuervo posted:

Is a Sqlite database with a single table the best way to store this data given the queries I want to run? The single table would have four columns (trial ID, subject ID, date time, and blood glucose value).

Yes that should be fine. You should be able to pick up the syntax of queries pretty easily

Jose Cuervo
Aug 25, 2004

Twerk from Home posted:

SQLite with a multi-column index on subject id and timestamp should work well. If you think you'll need to query by timestamp only but not subject only, reverse that order.

https://use-the-index-luke.com/sql/where-clause/the-equals-operator/concatenated-keys

The subject ID is not unique across different trials, so I would want a multi-column index with trial ID, subject ID, and timestamp, right? Or would it be more efficient to create a new column (say trial_subject) which concatenates trial ID and subject ID which would be a unique identifier for each subject's data, and then use a multi-column index with trial_subject and timestamp?

I will never need to query by timestamp only because even subjects in the same trial participated over different weeks / months, depending on when they enrolled, so I will always be specifying the trial, the subject, and the timestamp.

Foxfire_
Nov 8, 2010

Don't make a new column that's duplicating information from other columns. Having the primary key be (trial ID, subject ID, draw time timestamp) is fine if those are always unique. If those can be duplicated (i.e. data entry error, or two measurements from the same tube of blood), just have a surrogate primary key (autocreated meaningless ascending integer). Throw some indexes at it later if it actually is slow, but I'd be surprised if it matters.

You shouldn't overthink this; it's not a particularly large database and it's going to be bottlenecked by python slowness, not the database. Even for a poorly designed schema, most of the time is going to be spent creating python object versions of the results, not looking up the results themselves

Making up pessimistic numbers:
- 64 bytes text trial ID
- 64 bytes text subject ID
- 64 bytes timestamp because SQLite does datatypes bizarrely and will be storing text
- 8 bytes of floating point measurement
= 200 bytes per record * 20 million rows => ~4GB of database. That isn't particularly big.

Jose Cuervo
Aug 25, 2004

Foxfire_ posted:

Don't make a new column that's duplicating information from other columns. Having the primary key be (trial ID, subject ID, draw time timestamp) is fine if those are always unique. If those can be duplicated (i.e. data entry error, or two measurements from the same tube of blood), just have a surrogate primary key (autocreated meaningless ascending integer). Throw some indexes at it later if it actually is slow, but I'd be surprised if it matters.

You shouldn't overthink this; it's not a particularly large database and it's going to be bottlenecked by python slowness, not the database. Even for a poorly designed schema, most of the time is going to be spent creating python object versions of the results, not looking up the results themselves

Making up pessimistic numbers:
- 64 bytes text trial ID
- 64 bytes text subject ID
- 64 bytes timestamp because SQLite does datatypes bizarrely and will be storing text
- 8 bytes of floating point measurement
= 200 bytes per record * 20 million rows => ~4GB of database. That isn't particularly big.

So I am running into my first problems. I create my database and table as follows:
Python code:
import sqlite3

conn = sqlite3.connect('bg_time_series.db')
c = conn.cursor()
c.execute("""CREATE TABLE blood_glucose (
            trial_ID text,
            subject_ID text,
            date_time text,
            bg integer
            )""")
I have my time series data stored as CSV files (different CSV files for each of the trials), and I can read each CSV file into a pandas DataFrame. My plan then is to iterate over each row in the DataFrame and add that row of data to the database as follows:
Python code:
for _, row in df.iterrows():
    values_str = f'DCLP3, {row["SID"]}, {row["Date_Time"]}, {row["Value"]}'
    print(values_str)
    c.execute(f"INSERT INTO blood_glucose VALUES ({values_str})")
Which prints out the following error:
code:
DCLP3, DCLP3-001-001, 2017-12-02 00:05:33, 131

---------------------------------------------------------------------------
OperationalError                          Traceback (most recent call last)
<ipython-input-42-c97328299c38> in <module>
      2     values_str = f'DCLP3, {row["SID"]}, {row["Date_Time"]}, {row["Value"]}'
      3     print(values_str)
----> 4     c.execute(f"INSERT INTO blood_glucose VALUES ({values_str})")

OperationalError: near "00": syntax error
Not quite sure how to troubleshoot this.

Jose Cuervo fucked around with this message at 02:08 on Oct 31, 2022

QuarkJets
Sep 8, 2008

Don't form your own string of insert values, use placeholder binding instead:
https://docs.python.org/3/library/sqlite3.html#sqlite3-placeholders

Zoracle Zed
Jul 10, 2001
Because DCLP3 isn't quoted, it's being interpreted as a variable, not a string. Ideally you want your database api to handle string escaping for you because 1) it's a huge headache and 2) the whole sql injection thing once you need to worry about malicious data, etc. Should look more like this (can't remember if sqlite uses %s or just % as the placeholder):

code:
c.execute("INSERT INTO blood_glucose VALUES (%s, %s, %s, %s)", ('DCLP3, row["SID"], row["Date_Time"], row["Value"]))
note instead there's also a pandas method for dumping a dataframe to sqlite: https://pandas.pydata.org/pandas-docs/stable/reference/api/pandas.DataFrame.to_sql.html

but... if you've already got the data in memory as a dataframe, are you sure you want/need to use a database at all, instead of working directly on the dataframe?

Foxfire_
Nov 8, 2010

Jose Cuervo posted:

code:
DCLP3, DCLP3-001-001, 2017-12-02 00:05:33, 131

---------------------------------------------------------------------------
OperationalError                          Traceback (most recent call last)
<ipython-input-42-c97328299c38> in <module>
      2     values_str = f'DCLP3, {row["SID"]}, {row["Date_Time"]}, {row["Value"]}'
      3     print(values_str)
----> 4     c.execute(f"INSERT INTO blood_glucose VALUES ({values_str})")

OperationalError: near "00": syntax error
Not quite sure how to troubleshoot this.

You're handing "INSERT INTO blood_glucose VALUES (DCLP3, DCLP3-001-001, 2017-12-02 00:05:33, 131)" with all the values substituted into a string to the database engine to execute. That's problematic because it has to parse the individual values back out, and its parsing expects to see strings in quotes, not bare. For this insert, it'd want:
code:
INSERT INTO blood_glucose VALUES ("DCLP3", "DCLP3-001-001", "2017-12-02 00:05:33", 131)
You still don't want to try to do that escaping yourself because it's hard and error-prone (if this were important and random people had access to it, bugs would also lead to security problems i.e. https://xkcd.com/327/).

Instead of handing a mixed data+instructions query to the database engine, you want to be telling it "Execute this purely instructions query (that is coming from a string constant) using these purely-data parameter bindings"

To do that with python's sqlite interface, you use either "?" for the parameter values, or ":somename" for a named one, then provide the bindings when you run the query. QuarkJets is pointing you at the documentation for it.

The query would look something like this:

Python code:
c.execute(
    "INSERT INTO blood_glucose VALUES (?, ?, ?, ?)", 
    ("DCLP3", row["SID"], row["Date_Time"], row["Value"])
)
or
Python code:
c.execute(
    "INSERT INTO blood_glucose VALUES (:study, :subject, :draw_time, :measurement)", 
    {
        "study": "DCLP3", 
        "subject": row["SID"], 
        "draw_time": row["Date_Time"], 
        "measurement": row["Value"])
    }
)
There is also executemany() that will insert multiple rows at once.

Other stuff:
- If you don't ever want to have null/blank values, add "NOT NULL" to the columns when you create the database. It will yell at you if you try to do an insert or edit that does that.
- If your sqlite installation is new enough, adding STRICT to the table creation options will turn on strict mode and disable a bunch of Javascript-esque "when I ask for something that doesn't make sense, apply type conversions instead of reporting an error"
- If it were me and this was something that I might keep around after a couple month gaps, I'd stick the units for the glucose measurement in the column name

Cup Runneth Over
Aug 8, 2009

She said life's
Too short to worry
Life's too long to wait
It's too short
Not to love everybody
Life's too long to hate


Mods please rename thread "The Plaza of Python" tia

Macichne Leainig
Jul 26, 2012

by VG

QuarkJets posted:

Is posting in the thread somehow not letting people make their own decisions?

IMO if it's okay to post a job posting then it's also ok for people to remark on it in whatever way they want.

Yeah sure but dumb quips about how much money you make/made are useless

I could say I make $500k and even if it was true it adds just as little as the rest of my posts because nobody cares

Macichne Leainig fucked around with this message at 21:00 on Oct 31, 2022

QuarkJets
Sep 8, 2008

Macichne Leainig posted:

Yeah sure but dumb quips about how much money you make/made are useless

I could say I make $500k and even if it was true it adds just as little as the rest of my posts because nobody cares

That's an uncharitable reading of their posts; they were providing those numbers (which they probably didn't just make up) to support their opinion that the amount being offered in an earlier post is too low. That's informative; OP was offering data that may be useful to anyone interested in the offered position. And it provoked a discussion over what a fair internship salary should be, which was interesting

Jose Cuervo
Aug 25, 2004

QuarkJets posted:

Don't form your own string of insert values, use placeholder binding instead:
https://docs.python.org/3/library/sqlite3.html#sqlite3-placeholders

Thanks. I am going to read through the documentation more carefully which is what I should have done in the first place.

Zoracle Zed posted:

Because DCLP3 isn't quoted, it's being interpreted as a variable, not a string. Ideally you want your database api to handle string escaping for you because 1) it's a huge headache and 2) the whole sql injection thing once you need to worry about malicious data, etc. Should look more like this (can't remember if sqlite uses %s or just % as the placeholder):

code:
c.execute("INSERT INTO blood_glucose VALUES (%s, %s, %s, %s)", ('DCLP3, row["SID"], row["Date_Time"], row["Value"]))
note instead there's also a pandas method for dumping a dataframe to sqlite: https://pandas.pydata.org/pandas-docs/stable/reference/api/pandas.DataFrame.to_sql.html

but... if you've already got the data in memory as a dataframe, are you sure you want/need to use a database at all, instead of working directly on the dataframe?

I have a single one of the trials in a DataFrame, but there are multiple trials and I estimate there will be about 20 million rows or more once everything is read in, and I figured this would be a good time to use a database.

Foxfire_ posted:

You're handing "INSERT INTO blood_glucose VALUES (DCLP3, DCLP3-001-001, 2017-12-02 00:05:33, 131)" with all the values substituted into a string to the database engine to execute. That's problematic because it has to parse the individual values back out, and its parsing expects to see strings in quotes, not bare. For this insert, it'd want:
code:
INSERT INTO blood_glucose VALUES ("DCLP3", "DCLP3-001-001", "2017-12-02 00:05:33", 131)
You still don't want to try to do that escaping yourself because it's hard and error-prone (if this were important and random people had access to it, bugs would also lead to security problems i.e. https://xkcd.com/327/).

Instead of handing a mixed data+instructions query to the database engine, you want to be telling it "Execute this purely instructions query (that is coming from a string constant) using these purely-data parameter bindings"

To do that with python's sqlite interface, you use either "?" for the parameter values, or ":somename" for a named one, then provide the bindings when you run the query. QuarkJets is pointing you at the documentation for it.

The query would look something like this:

Python code:
c.execute(
    "INSERT INTO blood_glucose VALUES (?, ?, ?, ?)", 
    ("DCLP3", row["SID"], row["Date_Time"], row["Value"])
)
or
Python code:
c.execute(
    "INSERT INTO blood_glucose VALUES (:study, :subject, :draw_time, :measurement)", 
    {
        "study": "DCLP3", 
        "subject": row["SID"], 
        "draw_time": row["Date_Time"], 
        "measurement": row["Value"])
    }
)
There is also executemany() that will insert multiple rows at once.

Other stuff:
- If you don't ever want to have null/blank values, add "NOT NULL" to the columns when you create the database. It will yell at you if you try to do an insert or edit that does that.
- If your sqlite installation is new enough, adding STRICT to the table creation options will turn on strict mode and disable a bunch of Javascript-esque "when I ask for something that doesn't make sense, apply type conversions instead of reporting an error"
- If it were me and this was something that I might keep around after a couple month gaps, I'd stick the units for the glucose measurement in the column name

This made things work just right. I am going to read through the documentation some more, but things seem to be working just fine now and I seem to be able to query with no issues.

samcarsten
Sep 13, 2022

by vyelkin
Ok, got an example I have to do for class, and since the guys in the Java thread have been helpful, I'm here to ask you for Python stuff. What is a good primer for how to use APIs? The assignment for this week is to use the API for DuckDuckGo to search "presidents of the united states." In the "related Topics" field of the JSON response, all the presidents should be listed. I know how to compare lists, but how do I properly use an API? All I got given by my teacher was a link to a Linkedin video.

saintonan
Dec 7, 2009

Fields of glory shine eternal

samcarsten posted:

Ok, got an example I have to do for class, and since the guys in the Java thread have been helpful, I'm here to ask you for Python stuff. What is a good primer for how to use APIs? The assignment for this week is to use the API for DuckDuckGo to search "presidents of the united states." In the "related Topics" field of the JSON response, all the presidents should be listed. I know how to compare lists, but how do I properly use an API? All I got given by my teacher was a link to a Linkedin video.

if you type

code:
https://api.duckduckgo.com/?q=presidents%20of%20the%20united%20states&format=json&pretty=1
into a browser, you'll see what the API returns, including the fields you're looking for. Now all you have to do is make the JSON look pretty, and there are a few different ways you can do that in Python.

Falcon2001
Oct 10, 2004

Eat your hamburgers, Apollo.
Pillbug
In terms of libraries/etc to look into I think that Requests is probably the most straightforward one to use and the most popular.

https://requests.readthedocs.io/en/latest/

QuarkJets
Sep 8, 2008

Falcon2001 posted:

In terms of libraries/etc to look into I think that Requests is probably the most straightforward one to use and the most popular.

https://requests.readthedocs.io/en/latest/

Yeah iirc with requests it's stupidly easy to get a dict if you're expecting to receive a json object, like:
Python code:
import requests
response = requests.get("http://wherever")
print(response.json())
Look at what's contained in that dictionary and you should easily find what you're looking for

You may have to set a user-agent too, you can google how to do this

Data Graham
Dec 28, 2009

📈📊🍪😋



Is there any way to "alias" the @property decorator to something else?

I have a Django model which has a field called "property" already (i.e. referring to a real estate property) and it's making it impossible for me to make @property methods

Jabor
Jul 16, 2010

#1 Loser at SpaceChem
Can you just do _property = property somewhere in the file before the property field is defined?

Data Graham
Dec 28, 2009

📈📊🍪😋



I'll be damned, I can. Thanks!

CarForumPoster
Jun 26, 2013

⚡POWER⚡

Data Graham posted:

Is there any way to "alias" the @property decorator to something else?

I have a Django model which has a field called "property" already (i.e. referring to a real estate property) and it's making it impossible for me to make @property methods

Disclaimer: I feel like a novice ITT and rarely use classes or make Django apps anymore. I’ve never made a decorator though I think I know how they work from using them frequently.

Having a variable named property is like having a variable named list, yea? It’s gonna overwrite the property() built in that the decorator is calling, no? I’d think you COULD alias it by recreating the built in that the decorator @property is calling, but idk if you should.

If it’s an already deployed thing where there WILL be consequences from changing the model’s redefinition of property, then perhaps a property_decorator = property() that you import whenever you need the @property (now @property_decorator would solve this?

Again I’ve never done this in practice. Simple solution is to not use variable names that are built ins.

Data Graham
Dec 28, 2009

📈📊🍪😋



Yeah it's an already-deployed thing. I'm trying to clean it up and adding @propertys so it isnt().all().a().chain().of().things().like().this() is part of the effort

Falcon2001
Oct 10, 2004

Eat your hamburgers, Apollo.
Pillbug
I have some DI pattern questions, so general compsci stuff. This is for a project I'm moving away from (new job starts on Monday) but I'm curious about what the downside of the method I worked out is.

When I took over this project, we had a ton of module-level 'Global' variables for dependencies. This obviously was a nightmare for testing, but fixing it was difficult because I was working at the end of the 'chain' so to speak, so setting up full proper DI from the program start would involve a lot of refactoring.

I was generally trying to move to factory patterns instead of overloaded __init__ anyway, and struck upon this setup for handling this.

Python code:

class ProjectFactory

    def get_ext_dependency() -> ExtDependency:
        return ExtDependency()
        
    def get_diff_dependency(dep_override: DependencyThisThingNeeds = None) -> DiffDependency:
        if dep_override is None:
            dep_override = default_setting_for_this_option
        return DependencyThisThingNeeds(dep_override)

# Where you need to use it
import ProjectFactory
 
 ext = ProjectFactory.get_ext_dependency()
 diff_dep = ProjectFactory.get_diff_dependency()
When testing, it's easy enough to import and overwrite the ProjectFactory get* functions to return whatever mock for external dependencies you need, and your code doesn't need to have a ton of signatures for passing everything in one at a time.

Is this just a matter of 'when reading the code, you won't easily be able to see that a downstream function of this function uses this external dependency?' like an implicit vs explicit problem? Or are there other downsides of this pattern I'm not seeing due to lack of experience?

samcarsten
Sep 13, 2022

by vyelkin
Okay, so looking at the requests thing, it seems like it only takes dictionaries as queries. 'm only supposed to search with the string "presidents of the united states" How am I supposed to do that? I don't really understand the syntax.

Data Graham
Dec 28, 2009

📈📊🍪😋



samcarsten posted:

Okay, so looking at the requests thing, it seems like it only takes dictionaries as queries. 'm only supposed to search with the string "presidents of the united states" How am I supposed to do that? I don't really understand the syntax.

From this:

saintonan posted:

if you type

code:
https://api.duckduckgo.com/?q=presidents%20of%20the%20united%20states&format=json&pretty=1
into a browser, you'll see what the API returns, including the fields you're looking for. Now all you have to do is make the JSON look pretty, and there are a few different ways you can do that in Python.

See the q=presidents%20of%20the%20united%20states part? That's a key-value pair. The key is q and the value is presidents%20of%20the%20united%20states.

Dictionaries are for mapping keys to values. So make a dict like this:

Python code:
d = {
    'q': 'presidents of the united states'
}
And that's what you can pass into requests. You can probably figure out what to do with format and pretty.

(Requests will also handle urlencoding the spaces into %20 symbols for you.)

samcarsten
Sep 13, 2022

by vyelkin
ok, so my current code looks like this:

code:
import requests

print("Enter query: ")
query = input()
d = {'q': query}

r = requests.get('http://api.duckduckgo.com', d)

data = r.json()
However, I keep getting this error:

json.decoder.JSONDecodeError: Expecting value: line 1 column 1 (char 0)

I've googled it but none of the answers seem to help.

Data Graham
Dec 28, 2009

📈📊🍪😋



Those other keys in the query string I mentioned will be important.

12 rats tied together
Sep 7, 2006

Worth noting that Python has a pretty good interactive experience, right out of the box. If I run your code:
Python code:
>>> data = r.json()
Traceback (most recent call last):
  File "/home/rob/.pyenv/versions/3.10.4/lib/python3.10/site-packages/requests/models.py", line 910, in json
    return complexjson.loads(self.text, **kwargs)
  File "/home/rob/.pyenv/versions/3.10.4/lib/python3.10/json/__init__.py", line 346, in loads
    return _default_decoder.decode(s)
  File "/home/rob/.pyenv/versions/3.10.4/lib/python3.10/json/decoder.py", line 337, in decode
    obj, end = self.raw_decode(s, idx=_w(s, 0).end())
  File "/home/rob/.pyenv/versions/3.10.4/lib/python3.10/json/decoder.py", line 355, in raw_decode
    raise JSONDecodeError("Expecting value", s, err.value) from None
json.decoder.JSONDecodeError: Expecting value: line 1 column 1 (char 0)

# what is r?
>>> type(r)
<class 'requests.models.Response'>

# how can we talk to it?
>>> dir(r)
['__attrs__', '__bool__', '__class__', [...], 'content',  [...]  'status_code', 'text', 'url']

# r.content sounds promising
>>> r.content
b'<!DOCTYPE html>\n<!--[if IEMobile 7 ]> <html lang="en-US" class="no-js iem7"> <![endif]-->\n<!--[if lt IE 7]> <html class="ie6 lt-ie10 lt-ie9 lt-ie8 lt-ie7 no-js" lang="en-US"> <![endif]-->\n<!--[if IE 7]> # snip
This looks like HTML to me, so it's pretty reasonable that it would fail to parse as JSON.

12 rats tied together fucked around with this message at 20:53 on Nov 2, 2022

The March Hare
Oct 15, 2006

Je rêve d'un
Wayne's World 3
Buglord

samcarsten posted:

I've googled it but none of the answers seem to help.

12 rats are correct above, and I will add that you should try to become comfortable with the following as well:

code:
import requests

print("Enter query: ")
query = input()
d = {'q': query}

r = requests.get('http://api.duckduckgo.com', d)

# A simple print debugging approach is very similar to what rats posted, but you get to skip a lot of copy/pasting that may be unfeasible for longer/more complex logic chains than what your simple script is doing here.
print(r)

data = r.json()
code:
import requests

print("Enter query: ")
query = input()
d = {'q': query}

r = requests.get('http://api.duckduckgo.com', d)

# pdb will drop you into an interactive python shell where you can inspect everything with the full context of your program's execution available to you. Every minute you spend understanding how to use PDB (or any debugger) will pay itself back many times over, and the initial investment is only a few minutes getting a grip on the basic commands.

import pdb
pdb.set_trace()

data = r.json()

Adbot
ADBOT LOVES YOU

Falcon2001
Oct 10, 2004

Eat your hamburgers, Apollo.
Pillbug
I recommend iPython for a bit nicer of a commandline experience.

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