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
SurgicalOntologist
Jun 17, 2004

Munkeymon posted:

There are roughly three possibilities here:

They might just have that one hard-coded auth key, in which case you just keep using it and it's fine until they change something that'd probably break your scraper anyway.

The key might be loaded into some DOM node and read by a script, so you can probably do that same given that static page and a little legwork. Open the Chrome dev tools and search all with Ctrl[Option] + Shift[Command] + F and search for the key to see if it's just getting squirted out into a script element or something (this is likely).

It's derived from something the server sends. You're probably better off using Selenium in this case because they're being clever and paranoid.

In my experience it is almost always the last one, and it just happens because they have authentication on their backend--nothing especially clever or paranoid, any number of frameworks/packages would give that behavior by default out-of-the-box. All you have to do is mimic the login API calls just as you're mimicking the actual data fetching API calls. Usually opening a requests.Session and posting credentials to the login URL will put the authentication token in your session automatically. You typically don't even have to find it--just post your credentials (inside a session so you have persistent headers) and from then on you're authenticated.

Sometimes for the authentication you will find a situation like your second one, where you have to fetch the login page, find some token, then include it when you post your credentials.

Edit: actually I've been assuming that this is a website that requires a login. If it doesn't then I agree, you're probably in the second scenario there.

SurgicalOntologist fucked around with this message at 20:22 on Jan 11, 2018

Adbot
ADBOT LOVES YOU

ufarn
May 30, 2009
Is there a canonical way to parallellize a for loop that is compatible with 2.7? I've seen stuff like multiprocessing, concurrent.futures, and all sorts of stuff, but no idea which is the preferred option.

The loop has another loop inside it, but it's over like ten elements so it's not worth optimizing that part.

Thermopyle
Jul 1, 2003

...the stupid are cocksure while the intelligent are full of doubt. —Bertrand Russell

ufarn posted:

Is there a canonical way to parallellize a for loop that is compatible with 2.7? I've seen stuff like multiprocessing, concurrent.futures, and all sorts of stuff, but no idea which is the preferred option.

The loop has another loop inside it, but it's over like ten elements so it's not worth optimizing that part.

No, because it's dependent upon what kind of stuff is happening in the loop.

Thermopyle
Jul 1, 2003

...the stupid are cocksure while the intelligent are full of doubt. —Bertrand Russell

I have never had a need to do this, but I thought it was neat: Recover python source code if you've deleted the file but it's still in memory.

Slimchandi
May 13, 2005
That finger on your temple is the barrel of my raygun
If I have a container class, holding some instances of another class, is there a simple way to get the container to aggregate the results of the inner classes, without writing separate methods for the container for each inner class methods

Class Inner:

Def spades(self):
Return 'spades'

Def hearts(self):
Return 'hearts'

Def diamonds(self):
Return 'diamonds'

Class container:

Def __init__:
Self.children = [Inner(), Inner(), Inner()]


Def spades(self):
Return [inner.spades() for inner in self.children]

....


How can I avoid writing similar methods for hearts and diamonds, on the basis that the logic will be the same for all three? Preferably in a way that still works with code completion in Pycharm?

Thermopyle
Jul 1, 2003

...the stupid are cocksure while the intelligent are full of doubt. —Bertrand Russell

I'm so dependent upon formatting and syntax highlighting that I literally cannot read that post without significant effort.

Ghost of Reagan Past
Oct 7, 2003

rock and roll fun

Thermopyle posted:

I'm so dependent upon formatting and syntax highlighting that I literally cannot read that post without significant effort.

I mean without indentation it isn't valid Python anyway :v:

Slimchandi
May 13, 2005
That finger on your temple is the barrel of my raygun

accipter
Sep 12, 2003

Do you know about getattr?

Python code:
class container:
    def __init__(self):
        self.children = [Inner(), Inner(), Inner()]

    def get_card(self, card):
        return [getattr(inner, card)() for inner in self.children]

accipter fucked around with this message at 06:44 on Jan 13, 2018

Slimchandi
May 13, 2005
That finger on your temple is the barrel of my raygun
Yes, I'm familiar with it, but I was hoping to have something a bit more introspective on the Inner class that gave me code completion on the container class. Maybe I'm asking for too much.

QuarkJets
Sep 8, 2008

ufarn posted:

Is there a canonical way to parallellize a for loop that is compatible with 2.7? I've seen stuff like multiprocessing, concurrent.futures, and all sorts of stuff, but no idea which is the preferred option.

The loop has another loop inside it, but it's over like ten elements so it's not worth optimizing that part.

There are lots of options but I've always found multiprocessing the easiest to use and most widely applicable. If you have no idea what to use and don't want to explain the problem further then maybe give that a shot

Cingulate
Oct 23, 2012

by Fluffdaddy

QuarkJets posted:

There are lots of options but I've always found multiprocessing the easiest to use and most widely applicable. If you have no idea what to use and don't want to explain the problem further then maybe give that a shot
joblib is used in a bunch of scientific computing projects.

Wallet
Jun 19, 2006

Edit: Turns out the issue wasn't what I thought it was.

Wallet fucked around with this message at 17:09 on Jan 13, 2018

Master_Odin
Apr 15, 2010

My spear never misses its mark...

ladies

Slimchandi posted:

If I have a container class, holding some instances of another class, is there a simple way to get the container to aggregate the results of the inner classes, without writing separate methods for the container for each inner class methods


How can I avoid writing similar methods for hearts and diamonds, on the basis that the logic will be the same for all three? Preferably in a way that still works with code completion in Pycharm?

What are you trying to do here? Your example makes little sense to me. I'd probably have each suit (spade, heart, etc) be a class that inherits Inner, setting an internal class variable common to Inner to also denote suit and value.

tef
May 30, 2004

-> some l-system crap ->
Or use ('Hearts', 12) for the Queen of Hearts

Then if you use a set() instead of a custom container, you can write {card for card in deck if card[0] == 'Hearts'}

If you want, use a namedtuple so you can use card.suit or card.rank

Sad Panda
Sep 22, 2004

I'm a Sad Panda.
I've made a simple text game. It works just fine in a single file.

I've basically copied the whole class called Engine to a separate file (called Engine.py) and tried to import it as you can see.

Ex45.py
code:
import Engine

....
class Intro(Scene):
....

game = Engine.Engine()
Engine.py
code:
class Engine(object):

	def play(self):
		where = Intro()
		where.enter()
...
This throws up the error..

code:
    where = Intro()
NameError: name 'Intro' is not defined

baka kaba
Jul 19, 2003

PLEASE ASK ME, THE SELF-PROFESSED NO #1 PAUL CATTERMOLE FAN IN THE SOMETHING AWFUL S-CLUB 7 MEGATHREAD, TO NAME A SINGLE SONG BY HIS EXCELLENT NU-METAL SIDE PROJECT, SKUA, AND IF I CAN'T PLEASE TELL ME TO
EAT SHIT

Assuming you're importing Ex45 into Engine.py too (since you're calling Intro() and that class is defined in the other file), you've got a circular dependency - both modules depend on each other

There's an explanation here with examples - the problem is you start to load file A, and it gets to the import statement and has to load file B. File B wants to import A - and that's fine, it's happened already, but it hasn't finished loading A yet. So you get to the line where it tries to use something from file A, Python hasn't seen that function or class yet (it doesn't exist as far as it's concerned), so it throws an error

At this point you're probably thinking ugh this is bad and complicated and why did I bother - and yeah, often it's better to keep things in the same file. Or you have to organise the project so you don't get circular dependencies. If it's unavoidable, a lot of people recommend putting your imports at the end of the file (so they only run after the file has been fully loaded)

Sad Panda
Sep 22, 2004

I'm a Sad Panda.

baka kaba posted:

Assuming you're importing Ex45 into Engine.py too (since you're calling Intro() and that class is defined in the other file), you've got a circular dependency - both modules depend on each other

There's an explanation here with examples - the problem is you start to load file A, and it gets to the import statement and has to load file B. File B wants to import A - and that's fine, it's happened already, but it hasn't finished loading A yet. So you get to the line where it tries to use something from file A, Python hasn't seen that function or class yet (it doesn't exist as far as it's concerned), so it throws an error

At this point you're probably thinking ugh this is bad and complicated and why did I bother - and yeah, often it's better to keep things in the same file. Or you have to organise the project so you don't get circular dependencies. If it's unavoidable, a lot of people recommend putting your imports at the end of the file (so they only run after the file has been fully loaded)

Thank you. That makes perfect sense. I'd tried importing and got circular issues so tried briefly to see if I could fix it. Not worth the effort but something to keep in mind later. I did manage to export a different part to a separate file so that's all good.

Sad Panda fucked around with this message at 14:24 on Jan 15, 2018

The March Hare
Oct 15, 2006

Je rêve d'un
Wayne's World 3
Buglord
I don't know the full extent of your structure but you can also do imports inside of functions that need them to avoid circular imports.

unpacked robinhood
Feb 18, 2013

by Fluffdaddy
This is annoying. Why does this works fine:

code:
curl  -v "https://api_url.ext/service/service/find?y=48.73404&x=1.315607"
And this doesn't (the server returns a 404 page):

Python code:
    dreux = {'lat': 48.734040, 'lng': 1.315607}
    lng1 = dreux['lng']
    lat1 = dreux['lat']
    url_args = {'x': lng1, 'y': lat1}
    encoded_args = urlencode(url_args)
    base_host = "https://api_url.ext/service/service/find?"
    request_url = base_host + encoded_args
    http = HTTPSConnectionPool("api_url.ext/service", port=443)
    print('requesting {}'.format(request_url))
    response = http.request('GET', request_url)
    json_data = response.data
    data = json_data.decode('utf-8')
    print(data)
code:
$ ./Geocoding.py 
requesting [url]https://api_url.ext/service/find?y=48.73404&x=1.315607[/url]
<html><title>404: Not Found</title><body>404: Not Found</body></html>
$
ignore the [url] tags

unpacked robinhood fucked around with this message at 18:18 on Jan 17, 2018

Thermopyle
Jul 1, 2003

...the stupid are cocksure while the intelligent are full of doubt. —Bertrand Russell

unpacked robinhood posted:

This is annoying. Why does this works fine:

code:
curl  -v "https://domain/reverse/1.0/find?y=48.73404&x=1.315607"
And this doesn't (the server returns a 404 page):

Python code:
    dreux = {'lat': 48.734040, 'lng': 1.315607}
    lng1 = dreux['lng']
    lat1 = dreux['lat']
    url_args = {'x': lng1, 'y': lat1}
    encoded_args = urlencode(url_args)
    base_host = "https://domain/reverse/1.0/find?"
    request_url = base_host + encoded_args
    http = HTTPSConnectionPool("domain", port=443)
    print('requesting {}'.format(request_url))
    response = http.request('GET', request_url)
    json_data = response.data
    data = json_data.decode('utf-8')
    print(data)
code:
$ ./Geocoding.py 
requesting [url]https://domain/reverse/1.0/find?y=48.73404&x=1.315607[/url]
<html><title>404: Not Found</title><body>404: Not Found</body></html>
$
ignore the [url] tags

I barely looked at your code, but is there some reason you're not using python-requests? It's so widely used I'm surprised it's not in the standard library yet.

Thermopyle fucked around with this message at 18:22 on Jan 17, 2018

unpacked robinhood
Feb 18, 2013

by Fluffdaddy

Thermopyle posted:

I barely looked at your code, but is there some reason you're not using python-requests? It's so widely used I'm surprised it's not in the standard library yet.

I..didn't know this was a thing. I used urllib3 for the rest of my project and it worked good enough.

Thermopyle
Jul 1, 2003

...the stupid are cocksure while the intelligent are full of doubt. —Bertrand Russell

unpacked robinhood posted:

I..didn't know this was a thing. I used urllib3 for the rest of my project and it worked good enough.

It's been so long since I used urllib3 so don't take this to mean much, but I don't see anything wrong with your usage here.

They could be doing something stupid like white-listing user agent headers, but it'd be weird that they'd whitelist curl but not whatever UA urllib3 sends.

FWIW, Chrome loads that url fine here.

unpacked robinhood
Feb 18, 2013

by Fluffdaddy

Thermopyle posted:

It's been so long since I used urllib3 so don't take this to mean much, but I don't see anything wrong with your usage here.

They could be doing something stupid like white-listing user agent headers, but it'd be weird that they'd whitelist curl but not whatever UA urllib3 sends.

FWIW, Chrome loads that url fine here.

I know, it loads in any browser vOv. Seems to work perfectly with requests, thanks !

Do you mind scramling the API url a bit in your previous post (Or quote again my edited post) ?
This is another of those unprotected services they explicitely sell and I'd rather not have the URL show up in google results too much.
e: thanks for the edit

unpacked robinhood fucked around with this message at 18:24 on Jan 17, 2018

Thermopyle
Jul 1, 2003

...the stupid are cocksure while the intelligent are full of doubt. —Bertrand Russell

Scrambled.

Roundboy
Oct 21, 2008
as pointed out to me in the general question thread, we have a python thread, so here goes.

I have formatting configured in a json file to specifically add the logging.Formatter as:
code:
'%(asctime)s|%(filename)s|%(name)s|%(levelname)s|%(jobid)s|%(source)s|%(message)s'
jobid and source being my own variables i am appending to each log message which works swimmingly. The problem is when I use other imported modules that also use standard python logging like pysftp or googleauth that throw key errors dumping out their debug logs and complaining that they don;t know jobid or source ala :
code:
--- Logging error ---
Traceback (most recent call last):
  File "/usr/lib64/python3.5/logging/handlers.py", line 71, in emit
    if self.shouldRollover(record):
  File "/usr/lib64/python3.5/logging/handlers.py", line 187, in shouldRollover
    msg = "%s\n" % self.format(record)
  File "/usr/lib64/python3.5/logging/__init__.py", line 830, in format
    return fmt.format(record)
  File "/usr/lib64/python3.5/logging/__init__.py", line 570, in format
    s = self.formatMessage(record)
  File "/usr/lib64/python3.5/logging/__init__.py", line 539, in formatMessage
    return self._style.format(record)
  File "/usr/lib64/python3.5/logging/__init__.py", line 383, in format
    return self._fmt % record.__dict__
KeyError: 'jobid'
Call stack:
  File "/usr/lib64/python3.5/threading.py", line 882, in _bootstrap
    self._bootstrap_inner()
  File "/usr/lib64/python3.5/threading.py", line 914, in _bootstrap_inner
    self.run()
  File "/usr/local/lib/python3.5/site-packages/paramiko/transport.py", line 1908, in run
    handler(self.auth_handler, m)
  File "/usr/local/lib/python3.5/site-packages/paramiko/auth_handler.py", line 580, in _parse_userauth_success
    'Authentication ({}) successful!'.format(self.auth_method))
  File "/usr/local/lib/python3.5/site-packages/paramiko/auth_handler.py", line 75, in _log
    return self.transport._log(*args)
  File "/usr/local/lib/python3.5/site-packages/paramiko/transport.py", line 1687, in _log
    self.logger.log(level, msg, *args)
Message: 'Authentication (password) successful!'

I am having trouble wrapping my head around what the best approach is here. Can i create a custom logging class to auto add those variables to all logs regardless? Am I going about this all wrong ? What is the nest practice here? I cant get the proper google search terms to bring up what i want to happen, and the existing docs on logging dont seem to cover this situation.

Eela6
May 25, 2007
Shredded Hen

Roundboy posted:

as pointed out to me in the general question thread, we have a python thread, so here goes.

I have formatting configured in a json file to specifically add the logging.Formatter as:
code:
'%(asctime)s|%(filename)s|%(name)s|%(levelname)s|%(jobid)s|%(source)s|%(message)s'
jobid and source being my own variables i am appending to each log message which works swimmingly. The problem is when I use other imported modules that also use standard python logging like pysftp or googleauth that throw key errors dumping out their debug logs and complaining that they don;t know jobid or source ala :
code:
--- Logging error ---
Traceback (most recent call last):
  File "/usr/lib64/python3.5/logging/handlers.py", line 71, in emit
    if self.shouldRollover(record):
  File "/usr/lib64/python3.5/logging/handlers.py", line 187, in shouldRollover
    msg = "%s\n" % self.format(record)
  File "/usr/lib64/python3.5/logging/__init__.py", line 830, in format
    return fmt.format(record)
  File "/usr/lib64/python3.5/logging/__init__.py", line 570, in format
    s = self.formatMessage(record)
  File "/usr/lib64/python3.5/logging/__init__.py", line 539, in formatMessage
    return self._style.format(record)
  File "/usr/lib64/python3.5/logging/__init__.py", line 383, in format
    return self._fmt % record.__dict__
KeyError: 'jobid'
Call stack:
  File "/usr/lib64/python3.5/threading.py", line 882, in _bootstrap
    self._bootstrap_inner()
  File "/usr/lib64/python3.5/threading.py", line 914, in _bootstrap_inner
    self.run()
  File "/usr/local/lib/python3.5/site-packages/paramiko/transport.py", line 1908, in run
    handler(self.auth_handler, m)
  File "/usr/local/lib/python3.5/site-packages/paramiko/auth_handler.py", line 580, in _parse_userauth_success
    'Authentication ({}) successful!'.format(self.auth_method))
  File "/usr/local/lib/python3.5/site-packages/paramiko/auth_handler.py", line 75, in _log
    return self.transport._log(*args)
  File "/usr/local/lib/python3.5/site-packages/paramiko/transport.py", line 1687, in _log
    self.logger.log(level, msg, *args)
Message: 'Authentication (password) successful!'

I am having trouble wrapping my head around what the best approach is here. Can i create a custom logging class to auto add those variables to all logs regardless? Am I going about this all wrong ? What is the nest practice here? I cant get the proper google search terms to bring up what i want to happen, and the existing docs on logging dont seem to cover this situation.

The problem here is that you're specifying behavior for logging.Formatter that relies on information that logging.Formatter doesn't have.

Instead, you should probably specify formatting behavior for a subclass of logging.Formatter that you control. Logs you create will use the special behavior, but other logs will be unaffected.

Slimchandi
May 13, 2005
That finger on your temple is the barrel of my raygun
Trying to read up on abstract base classes, found a few tutorials and Pycon videos but they all seem a bit shallow in their explanation.

Have I got this roughly right?

- Abstract base classes are designed not to be called directly, but inherited from. ABCs force derived classes to implement their 'abstract' methods.

- If any of these method is not implemented in a derived class, TypeError is thrown when the program tries to run.

- An ABC may fully implement some of these abstract methods, or simply pass, leaving the derived class to handle the implementation.

- Likewise, the derived class may override an abstract method, or make a call to super() and use the ABCs implementation directly (inheritance of abstract methods is not permitted)

If I've got this correct (and that's a big if), then I can see the use of ABCs when are writing classes that others will use or have complex structures, as you need to enforce those methods for the whole thing to work.

But even if the object I'm describing in my class is 'abstract' (e.g. Bird), which I never call directly, and I only use it to subclass instances of 'real' birds (Gull, Eagle, Owl), this situation wouldn't benefit from using an ABC. I would be better off with a standard Bird class that I inherit from, right?

wolrah
May 8, 2006
what?

unpacked robinhood posted:

This is annoying. Why does this works fine:

You goofed a bit when editing it and have part of the path in the HTTPSConnectionPool line, which causes a HostChangedError exception.

After correcting that and tweaking the URL a bit to point at a valid destination on a server I control, I see definite differences in the request and the resulting server responses in my nginx logs.

code:
10.0.0.1 - - [17/Jan/2018:14:08:58 -0500] "GET https://domain.tld/Unsorted/?y=48.73404&x=1.315607 HTTP/1.1" 200 5 "-" "-"
10.0.0.1 - - [17/Jan/2018:14:09:39 -0500] "GET /Unsorted/?y=48.73404&x=1.315607 HTTP/2.0" 200 3877 "-" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/64.0.3282.85 Safari/537.36"
The top one is the request from the modified version of your code, the bottom is from Chrome. You're requesting the full URL as the path, so it's effectively requesting https://api_url.ext/https://api_url.ext/service/service/find?y=48.73404&x=1.315607

I then cut down the base_host line to remove the host and leave only the path and I get this:

code:
10.0.0.1 - - [17/Jan/2018:14:11:53 -0500] "GET /Unsorted/?y=48.73404&x=1.315607 HTTP/1.1" 200 5 "-" "-"
10.0.0.1 - - [17/Jan/2018:14:12:15 -0500] "GET /Unsorted/?y=48.73404&x=1.315607 HTTP/2.0" 200 3833 "-" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/64.0.3282.85 Safari/537.36"
The request is sent as HTTP 1.1 rather than 2.0 and doesn't have a user agent, but that shouldn't matter in either case for a single response. Why my server returns basically an empty 5 bytes rather than the directory listing it sends to Chrome I have no idea.

Here's another test from a third-party service:

code:
54.87.29.64 - - [17/Jan/2018:14:28:30 -0500] "GET /Unsorted/?y=48.73404&x=1.315607 HTTP/1.1" 200 3633 "-" "runscope/0.1"
That also gets the full response.

I've switched it to HTTP so I can see the actual request data easily and here's what's showing up in Wireshark...

Here's the request your code is sending:

code:
GET /Unsorted/?y=48.73404&x=1.315607 HTTP/1.1
Host: domain.tld
Accept-Encoding: identity
Here's the external service:

code:
GET /Unsorted/?y=48.73404&x=1.315607 HTTP/1.1
Host: domain.tld
Accept: */*
User-Agent: runscope/0.1
Accept-Encoding: gzip, deflate
and here's Chrome

code:
GET /Unsorted/?y=48.73404&x=1.315607 HTTP/1.1
Host: domain.tld
Connection: keep-alive
Upgrade-Insecure-Requests: 1
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/64.0.3282.85 Safari/537.36
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8
Accept-Encoding: gzip, deflate
Accept-Language: en-US,en;q=0.9
Cookie: PHPSESSID=53n951a2a9nc6t6nbe248pr9n4
At least on my server, setting the user agent header got it to respond as expected. Not sure why that is, I'm running pretty much out of the box nginx as just a way to access my file server remotely so it shouldn't care what's requesting data.

I did that by adding
code:
headers={"User-Agent" : "blahblahblahfuck"}
to the http.request line.

So in summary it looks like your requests were set up wrong so it was requesting the URL as the path which is the cause of your 404, and possibly the user agent thing as well.

wolrah fucked around with this message at 20:53 on Jan 17, 2018

Nippashish
Nov 2, 2005

Let me see you dance!

Slimchandi posted:

But even if the object I'm describing in my class is 'abstract' (e.g. Bird), which I never call directly, and I only use it to subclass instances of 'real' birds (Gull, Eagle, Owl), this situation wouldn't benefit from using an ABC. I would be better off with a standard Bird class that I inherit from, right?

I wouldn't use an ABC unless at least one of the methods was going to be abstract. In this case the advantage of an abstract foo over def foo(): pass in the base class is that python will yell at you if you forget to implement foo in the subclass, instead of just calling the empty method and plowing ahead. If this is not a thing you care about then you have no reason to use ABCs.

Eela6
May 25, 2007
Shredded Hen

Slimchandi posted:

Trying to read up on abstract base classes, found a few tutorials and Pycon videos but they all seem a bit shallow in their explanation.

Have I got this roughly right?

- Abstract base classes are designed not to be called directly, but inherited from. ABCs force derived classes to implement their 'abstract' methods.

- If any of these method is not implemented in a derived class, TypeError is thrown when the program tries to run.

- An ABC may fully implement some of these abstract methods, or simply pass, leaving the derived class to handle the implementation.

- Likewise, the derived class may override an abstract method, or make a call to super() and use the ABCs implementation directly (inheritance of abstract methods is not permitted)

If I've got this correct (and that's a big if), then I can see the use of ABCs when are writing classes that others will use or have complex structures, as you need to enforce those methods for the whole thing to work.


You've got it.



Slimchandi posted:


But even if the object I'm describing in my class is 'abstract' (e.g. Bird), which I never call directly, and I only use it to subclass instances of 'real' birds (Gull, Eagle, Owl), this situation wouldn't benefit from using an ABC. I would be better off with a standard Bird class that I inherit from, right?
Yes. ABCs are not really meant for production code. They're meant for designing user-extensible frameworks.

Alex Martelli, in Luciano Ramalho's Fluent Python, pg. 331 posted:

"ABC's are meant to encapsulate very general concepts, abstractions, introduced by a framework - things like "a sequence" and "an exact number". [Readers] most likely don't need to write any new ABCs, just use existing ones correctly, to get 99.9% of the benefits without serious risk of misdesign.

Eela6 fucked around with this message at 21:05 on Jan 17, 2018

Roundboy
Oct 21, 2008

Eela6 posted:

The problem here is that you're specifying behavior for logging.Formatter that relies on information that logging.Formatter doesn't have.

Instead, you should probably specify formatting behavior for a subclass of logging.Formatter that you control. Logs you create will use the special behavior, but other logs will be unaffected.

makes sense, but is this possible to hold this in a config.json or will that formatter need to be imported / added to each script ? Originally it was nice to have a central file controlling all the logging formats, but I inherited this and trying to fix it in a unified way.

Slimchandi
May 13, 2005
That finger on your temple is the barrel of my raygun
Thanks.

Fluent Python is a mystery to me. I look at the next chapter, read a few pages and think 'where am I gonna use that sort of crazy thing in my code?'. A few weeks later someone posts a section of it explaining the very thing I'm stuck on. Probably happened 3 or 4 times now.

Eela6
May 25, 2007
Shredded Hen
It is an extremely through text. There's a lot to take in.

Eela6 fucked around with this message at 22:47 on Jan 17, 2018

unpacked robinhood
Feb 18, 2013

by Fluffdaddy

Thanks for the various commented tests. It feels like I double checked those lines a dozen times but missed this.
I'm using requests now, which works so far.

The March Hare
Oct 15, 2006

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

unpacked robinhood posted:

I'm using requests now, which works so far.

Very good move.

To whoever was asking why it wasn't in stdlib earlier: https://speakerdeck.com/kennethreitz/python-requests-and-the-standard-library

Hed
Mar 31, 2004

Fun Shoe

The March Hare posted:

Very good move.

To whoever was asking why it wasn't in stdlib earlier: https://speakerdeck.com/kennethreitz/python-requests-and-the-standard-library

Thanks for that. I figured it would boil down to "putting in the stdlib involves losing agility". I get it.

KernelSlanders
May 27, 2013

Rogue operating systems on occasion spread lies and rumors about me.
One could use that argument to exclude anything from the standard library.

NtotheTC
Dec 31, 2007


Does anyone know if pipenv can replicate the behaviour of vex? (https://pypi.python.org/pypi/vex) I've always found vex to be lightyears ahead of virtualenvwrapper for development (activating and deactivating virtualenvs manually is a horrible pattern) but I've never used pipenv and people seem very happy with it

To be clear, the behaviour I want to replicate is

Bash code:
vex myenv python myscript.py
instead of
Bash code:
workon myenv
python myscript.py
deactivate myenv

NtotheTC fucked around with this message at 15:22 on Jan 21, 2018

Adbot
ADBOT LOVES YOU

Nippashish
Nov 2, 2005

Let me see you dance!

NtotheTC posted:

To be clear, the behaviour I want to replicate is

I have endless copies of
code:
#!/bin/bash

source $(pwd)/venv/bin/activate
"$@"
hanging around in my projects. The end result looks pretty similar to what you want because env changes made inside a script don't propogate out to the surrounding environment so I can type ./run.sh python my_script.py and it does the right thing.

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