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
beetlemeyer
Dec 31, 2019
Python 3 jumped the shark. Guido tried really hard to understand async (neé twisted) but he ran away.

What brilliant poo poo are they going to come up with for 4?

Adbot
ADBOT LOVES YOU

Cosa Nostra Aetate
Jan 1, 2019

beetlemeyer posted:

Python 3 jumped the shark. Guido tried really hard to understand async (neé twisted) but he ran away.

What brilliant poo poo are they going to come up with for 4?

- Make Python statically typed: mypyc becomes part of core
- pypy goes the way of Jython
- No more pypi, its just not working out so they start fresh by imitating go!
- Add more operators that make emoji part of the language:
- 🐘: used to inline C
- 💩: used to trigger garbage collection
- 💍: used to make promises as a part of async3
- maybe get rid of the GIL?

Macichne Leainig
Jul 26, 2012

by VG
Gonna be more groundbreaking than that. Maybe they’ll finally give us full else if statements.

Bruegels Fuckbooks
Sep 14, 2004

Now, listen - I know the two of you are very different from each other in a lot of ways, but you have to understand that as far as Grandpa's concerned, you're both pieces of shit! Yeah. I can prove it mathematically.
Instead of semantic whitespace, blocks are now signified using braces. However, for backwards compatibility, semantic whitespace is still supported, but your code throws an exception if your code contains spaces/ tabs and a brace in the same file.

Bruegels Fuckbooks fucked around with this message at 15:11 on Jul 3, 2020

QuarkJets
Sep 8, 2008

We've added formal switch statements. Unfortunately, this breaks the pathlib module; everyone has to go back to using os.path.

Phobeste
Apr 9, 2006

never, like, count out Touchdown Tom, man
All .py files must have encoding declarations and if they don’t there will be an error. Also major strides have been made in lazy bytecode compilation. Sadly these errors combine to mean the error from encoding cannot be associated with a specific python file.

mr_package
Jun 13, 2000
I'm using secrets.token_hex() and want to know the max value it might generate, e.g. secrets.token_hex(nbytes=1) the max value is 255 (0xFF), 2 nbytes is 0xFFFF (65535), etc. Is there a simple way to figure out max int value of a given number of bytes / 'nbytes'?

edit:

return pow(2, 8 * nbytes) - 1

mr_package fucked around with this message at 23:12 on Jul 6, 2020

QuarkJets
Sep 8, 2008

How do people feel about using the exponentiation operator ** vs pow()? I tend to use **

mr_package
Jun 13, 2000
Yeah I used that actually, pretty sure it's the more common way.

Zoracle Zed
Jul 10, 2001
Anyone have any experience with making custom Conda forge recipes? There’s a library I’d like to use that has a couple of c++ dependencies that are available on Conda forge as Linux binaries but not windows, which is what I’m using. But all of these dependencies have appveyor scripts to ensure they build successfully on windows. So... it should be possible to wrap all of them up in a custom Conda recipe so I don’t have to build them manually myself, right?

God I hate dependency janitoring

KICK BAMA KICK
Mar 2, 2009

Was composing in my head a question that should probably go in the general question thread (nobody ever made that Docker thread that gets speculated about every time it comes up here, did they), but then had a realization that is Python-specific.

The general question is, what's the best practice for developing a Docker project on Windows that (of course) will use Linux-based containers, and it includes some text files like entrypoint scripts or configuration files that get copied into those containers and handling the DOS vs. Unix line-ending issue? For now I have a build stage using I think it's the codeimpossible/dos2unix image to convert the files before copying them into the Alpine-based containers that don't have that utility available, and it works fine but it bugs me that this workaround that's just contingent on how I happen to develop has to live in my codebase.

But this only comes up for like my Nginx container -- why is the CRLF issue not also a problem with my Python code running in containers based on in the official Debian-based Python images, cause it never has been?

SurgicalOntologist
Jun 17, 2004

Zoracle Zed posted:

Anyone have any experience with making custom Conda forge recipes? There’s a library I’d like to use that has a couple of c++ dependencies that are available on Conda forge as Linux binaries but not windows, which is what I’m using. But all of these dependencies have appveyor scripts to ensure they build successfully on windows. So... it should be possible to wrap all of them up in a custom Conda recipe so I don’t have to build them manually myself, right?

God I hate dependency janitoring

I wrapped some external c++ dependencies in conda forge recipes like 4 years ago. It wasn't too hard although I didn't have to deal with any Windows bullshit. The recipe is just the instructions though, you still have to build the recipe somewhere.

Zoracle Zed
Jul 10, 2001

SurgicalOntologist posted:

I wrapped some external c++ dependencies in conda forge recipes like 4 years ago. It wasn't too hard although I didn't have to deal with any Windows bullshit. The recipe is just the instructions though, you still have to build the recipe somewhere.

Oh drat, I was under the impression that conda-forge did some CI server type thing that would actually build the recipe for me.

SurgicalOntologist
Jun 17, 2004

Well come to think of it I was doing this before conda-forge. I just checked the website and you may be right!

Nohearum
Nov 2, 2013
Sorry if this has been discussed before but is anyone in here being impacted by the change in TOS for Anaconda? It's been a while since we upgraded versions my workplace but the licensing terms appear to have changed significantly for the 2020 version and they seem to be saying any use by companies (even internal-only use) requires a paid license.

QuarkJets
Sep 8, 2008

Nohearum posted:

Sorry if this has been discussed before but is anyone in here being impacted by the change in TOS for Anaconda? It's been a while since we upgraded versions my workplace but the licensing terms appear to have changed significantly for the 2020 version and they seem to be saying any use by companies (even internal-only use) requires a paid license.

Can you quote the relevant sections?

Macichne Leainig
Jul 26, 2012

by VG
That seems like a bad business idea.

The EULA for the Individual Edition software package is basically the BSD 3-clause license agreement:

https://docs.anaconda.com/anaconda/eula/

Looks quite permissive to me.

Nohearum
Nov 2, 2013

QuarkJets posted:

Can you quote the relevant sections?


Protocol7 posted:

That seems like a bad business idea.

The EULA for the Individual Edition software package is basically the BSD 3-clause license agreement:

https://docs.anaconda.com/anaconda/eula/

Looks quite permissive to me.

That Eula is what we saw in the past but our IT guy got directed to this page: https://know.anaconda.com/TOS.html
Some highlights...

quote:

These Terms of Service (“Agreement”) relate to your use of the compilation of products and tools made available by Anaconda through https://repo.anaconda.com/ and through our installers and applications (the “Repository”)...
...we are not granting you permission to use the Repository for large-scale commercial activities, such as downloading or mirroring the entire Repository or use of the Repository by multiple members of the business you work for.

At first I thought we were ok since we just pull their individual edition installer and use whatever is included in the base installation (our firewalls won't let our installation phone home to repo.anaconda.com to pull other packages...I do understand their concerns about companies constantly hammering their servers with lots of download requests ala npm). But there is a line that defines the "Repository" to include the installers, which is making our IT people paranoid about non-compliance.

I think Anaconda knows they can't charge for the packages themselves due to the licensing terms of each package so they are trying to make the entire bundle the product. They do a good job building a toolset that works out of the box and I'd like to support them but for our usage the cost could be pretty steep.

Nohearum fucked around with this message at 19:54 on Jul 10, 2020

Macichne Leainig
Jul 26, 2012

by VG
Yeah, large scale companies constantly hammering their servers with lots of download requests is a serious concern. I don't think it forbids you from using the software in a commercial context at all though.

If you're just using the Individual Edition installer, it sounds like you could probably figure out some way to download it once and store it somewhere to be downloaded anywhere on your company intranet. But I'm not sure how applicable that is to your use case.

QuarkJets
Sep 8, 2008

Yeah the TOS is describing "large-scale commercial activities", e.g. usage beyond small potatoes stuff, like mirroring their entire repository or installing Anaconda on every system on your network. Are these things that you plan to do? They're not drawing a clear line in the sand but if you have 20 Anaconda users all pulling from the repository then you should probably look at Enterprise

QuarkJets
Sep 8, 2008

If you create just one environment and create an installer that just unpacks it then that's probably the friendly and cheap solution. If you have a lot of users that want their own conda environments then enterprise is really what you need anyway, regardless of what the TOS says

Zoracle Zed
Jul 10, 2001

Zoracle Zed posted:

Anyone have any experience with making custom Conda forge recipes? There’s a library I’d like to use that has a couple of c++ dependencies that are available on Conda forge as Linux binaries but not windows, which is what I’m using. But all of these dependencies have appveyor scripts to ensure they build successfully on windows. So... it should be possible to wrap all of them up in a custom Conda recipe so I don’t have to build them manually myself, right?

God I hate dependency janitoring

Commenting on my own post because this turned out to be easier than I thought it would and maybe it will be useful for someone.

A package foo at https://anaconda.org/conda-forge/foo has a recipe repo at https://github.com/conda-forge/foo-feedstock. (it's weird the conda-forge listing doesn't link to this.)

Fork the feedstock repo, remove
code:
skip: True  # [win]
from meta.yaml, and add a bld.bat to the recipe folder:

code:
mkdir build && cd build

cmake -G "NMake Makefiles"^
    -DCMAKE_BUILD_TYPE=Release^
    -DCMAKE_INSTALL_PREFIX=%LIBRARY_PREFIX%^
    -DCMAKE_PREFIX_PATH=%LIBRARY_PREFIX%^
    -DCMAKE_INSTALL_LIBDIR=lib^
    %SRC_DIR%

if errorlevel 1 exit 1

nmake
if errorlevel 1 exit 1

nmake install
if errorlevel 1 exit 1
Commit the changes, then run "conda smithy rerender -c auto" which does some magic with CI authorization tokens. Then submit a pull request and hope it builds successfully.

Kinda neat!

Whybird
Aug 2, 2009

Phaiston have long avoided the tightly competetive defence sector, but the IRDA Act 2052 has given us the freedom we need to bring out something really special.

https://team-robostar.itch.io/robostar


Nap Ghost
Hi! I'm coming to Python from a more strongly typed language and there's an aspect of BAFP and duck typing that I'm trying to get my head round and which none of the tutorials I've read seem to focus on. It's more a question of what's right in principle than an actual live example.

Supposing I've got a list of objects of varying classes. Some of them have a particular kind of functionality, say, they define a particular method, and some of them don't. I want to run this method on any objects that have it defined, but I'd expect them to be in a minority.

Is it still the right thing to do to loop through all the items in my list and use a try/except clause on each to see if the method exists? It feels like the exception I'm catching in this case isn't really an exception but expected behaviour -- but is that just a question of semantics and actually exceptions can be things you'd expect to happen the majority of the time?

Extortionist
Aug 31, 2001

Leave the gun. Take the cannoli.
If you expect it to only going to be defined on some objects, I'd probably use hasattr/getattr instead.

code:
for obj in objects:
    if hasattr(obj, 'expected_func'):
        result = obj.expected_func()
	# or result = getattr(obj, 'expected_func')()
code:
for obj in objects:
    func = getattr(obj, 'expected_func', None)
    result = func() if func else None

CarForumPoster
Jun 26, 2013

⚡POWER⚡

Whybird posted:


Is it still the right thing to do to loop through all the items in my list and use a try/except clause on each to see if the method exists? It feels like the exception I'm catching in this case isn't really an exception but expected behaviour -- but is that just a question of semantics and actually exceptions can be things you'd expect to happen the majority of the time?

I'm not a python expert but the answer to these questions in my experience are: Sometimes. and Sometimes.

I tend to use isinstance() for type checking partially because its nice and readable.

That said when with web scraping or testing using selenium, I use try excepts when looking for elements instead of if statements everywhere as missing elements throw exceptions.

Macichne Leainig
Jul 26, 2012

by VG
I'm not crazy in thinking this is egregiously bad usage of the MySQL connector, right?

Python code:
import mysql.connector as mysql

mysql_connection = mysql.connect(**dbConfig)
cursor = mysql_connection.cursor()

def get_records(name):
    cursor.execute("SELECT * FROM table")
    return cursor.fetchall()
Basically, defining a global level connection and cursor and reusing it infinitely.

Isn't it better to do it more like this:

Python code:
def get_records(name):
    mysql_connection = mysql.connect(**dbConfig)
    cursor = mysql_connection.cursor()
    cursor.execute("SELECT * FROM table")
    records = cursor.fetchall()
    cursor.close()
    mysql_connection.close()
    return records
Where the connection and cursor only live for the duration of the function? (Probably better with try/catch/finally, but you get the idea.)

And would you like to guess which style my offshore guys used, leading to "mysql.connector.errors.OperationalError: MySQL Connection not available" errors?

M. Night Skymall
Mar 22, 2012

Whybird posted:

Hi! I'm coming to Python from a more strongly typed language and there's an aspect of BAFP and duck typing that I'm trying to get my head round and which none of the tutorials I've read seem to focus on. It's more a question of what's right in principle than an actual live example.

Supposing I've got a list of objects of varying classes. Some of them have a particular kind of functionality, say, they define a particular method, and some of them don't. I want to run this method on any objects that have it defined, but I'd expect them to be in a minority.

Is it still the right thing to do to loop through all the items in my list and use a try/except clause on each to see if the method exists? It feels like the exception I'm catching in this case isn't really an exception but expected behaviour -- but is that just a question of semantics and actually exceptions can be things you'd expect to happen the majority of the time?

I think it's "pythonic" to use try/except for flow control, that's how I was taught forever ago and googling seems to back me up as that still being the intention. Obviously still up to you if you actually want to program that way, I do a lot of try/except for checking types/existence of things and once you get used to it in Python it's easy to read things written that way.

Dominoes
Sep 20, 2007

Whybird: That feels like a misuse of exception handling. Instead, you could have a boolean or enum field that defines whether the method code is applicable. Post an example for a more detailed answer.

Dominoes fucked around with this message at 17:10 on Jul 16, 2020

Malcolm XML
Aug 8, 2009

I always knew it would end like this.

M. Night Skymall posted:

I think it's "pythonic" to use try/except for flow control, that's how I was taught forever ago and googling seems to back me up as that still being the intention. Obviously still up to you if you actually want to program that way, I do a lot of try/except for checking types/existence of things and once you get used to it in Python it's easy to read things written that way.

Python for loops use stopiteration exceptions for flow control so it's 100% blessed

Heck all generators do because they are equivalent to coroutines

NinpoEspiritoSanto
Oct 22, 2013




Protocol7 posted:

I'm not crazy in thinking this is egregiously bad usage of the MySQL connector, right?

Python code:
import mysql.connector as mysql

mysql_connection = mysql.connect(**dbConfig)
cursor = mysql_connection.cursor()

def get_records(name):
    cursor.execute("SELECT * FROM table")
    return cursor.fetchall()
Basically, defining a global level connection and cursor and reusing it infinitely.

Isn't it better to do it more like this:

Python code:
def get_records(name):
    mysql_connection = mysql.connect(**dbConfig)
    cursor = mysql_connection.cursor()
    cursor.execute("SELECT * FROM table")
    records = cursor.fetchall()
    cursor.close()
    mysql_connection.close()
    return records
Where the connection and cursor only live for the duration of the function? (Probably better with try/catch/finally, but you get the idea.)

And would you like to guess which style my offshore guys used, leading to "mysql.connector.errors.OperationalError: MySQL Connection not available" errors?

Doesn't mysql.connector support connection pools? Probably OK to have a global connection in that case so a connection can be reused instead of the usual bring up/teardown overhead. That said if it's an option to not use mysql.connector, take it. mysqlclient/pymysql are both more widely used, well maintained and most importantly, Not Oracle.

Macichne Leainig
Jul 26, 2012

by VG

Bundy posted:

Doesn't mysql.connector support connection pools? Probably OK to have a global connection in that case so a connection can be reused instead of the usual bring up/teardown overhead. That said if it's an option to not use mysql.connector, take it. mysqlclient/pymysql are both more widely used, well maintained and most importantly, Not Oracle.

Yeah, I don't really know why they chose mysql.connector specifically, I like to use SQLAlchemy on top of mysqlclient/pymysql personally. Maybe I just need to distribute an example Python project with that setup to them.

I'm sure the global connection is fine, but the global cursor seemed to be a problem, because it gets .close()'d at some point.

QuarkJets
Sep 8, 2008

Whybird posted:

Hi! I'm coming to Python from a more strongly typed language and there's an aspect of BAFP and duck typing that I'm trying to get my head round and which none of the tutorials I've read seem to focus on. It's more a question of what's right in principle than an actual live example.

Supposing I've got a list of objects of varying classes. Some of them have a particular kind of functionality, say, they define a particular method, and some of them don't. I want to run this method on any objects that have it defined, but I'd expect them to be in a minority.

Is it still the right thing to do to loop through all the items in my list and use a try/except clause on each to see if the method exists? It feels like the exception I'm catching in this case isn't really an exception but expected behaviour -- but is that just a question of semantics and actually exceptions can be things you'd expect to happen the majority of the time?

Hello! Welcome to Python

One bit of semantics: Python is strongly, dynamically typed. Strongly typed: there's no reinterpret_cast, and a string of digits isn't suddenly going to be interpreted as a number. Dynamic: Variables can be any type and can change types, but the objects that they represent are not changing types. It may be easier to think of variables as not having any type, but the object that a variable points to has a very specific type.

try/except blocks are a legitimate way to implement flow control. Using isinstance to test type is allowed, but it's discouraged since it often is used to violate the principle of duck typing, which you've picked up on as being a Python thing. The principle behind duck typing is that the object type shouldn't matter; if some code runs on strings and I implement a new class that looks exactly like a string, then that code should run on my new class as well. If execution fails because I failed to implement some essential string feature, then that should be caught and dealt with.

If you have control over what goes into the list, try to only insert objects that you know are going to implement the features that you expect before iterating over it. If you don't have control over what goes into the list, c'est la vie; do what you're doing, with a try/except block that handles cases where the object does not have whatever methods/attributes you expect.

NinpoEspiritoSanto
Oct 22, 2013




Protocol7 posted:

Yeah, I don't really know why they chose mysql.connector specifically, I like to use SQLAlchemy on top of mysqlclient/pymysql personally. Maybe I just need to distribute an example Python project with that setup to them.

I'm sure the global connection is fine, but the global cursor seemed to be a problem, because it gets .close()'d at some point.

Yeah global cursor is suspect indeed.

QuarkJets
Sep 8, 2008

Protocol7 posted:

I'm not crazy in thinking this is egregiously bad usage of the MySQL connector, right?

Python code:
import mysql.connector as mysql

mysql_connection = mysql.connect(**dbConfig)
cursor = mysql_connection.cursor()

def get_records(name):
    cursor.execute("SELECT * FROM table")
    return cursor.fetchall()
Basically, defining a global level connection and cursor and reusing it infinitely.

Isn't it better to do it more like this:

Python code:
def get_records(name):
    mysql_connection = mysql.connect(**dbConfig)
    cursor = mysql_connection.cursor()
    cursor.execute("SELECT * FROM table")
    records = cursor.fetchall()
    cursor.close()
    mysql_connection.close()
    return records
Where the connection and cursor only live for the duration of the function? (Probably better with try/catch/finally, but you get the idea.)

And would you like to guess which style my offshore guys used, leading to "mysql.connector.errors.OperationalError: MySQL Connection not available" errors?

In mysql terms it's preferred to reuse existing connections rather than constantly reopening and closing them. But connections can go stale, so if there's any chance of the cursor sitting unused for awhile then the connection will close and an exception will be raised. You can alter this timeout, if necessary

At the same time I am strongly opposed to most uses of global variables. There are good times to use them, but a global mysql connection is rarely going to be one. So I don't think you're crazy at all

I prefer passing around an open connection as a keyword argument and checking to see if it's still open before proceeding. This is easy to set up as a decorator that checks kwargs. Now all of your functions/methods can be easily decorated to reuse a common mysql connector that handles staleness without resorting to a global object. Your function is fine, but may be less fine if that function is being called frequently; it sucks to reopen and close a connection every 50 ms or whatever.

Protocol7 posted:

Yeah, I don't really know why they chose mysql.connector specifically, I like to use SQLAlchemy on top of mysqlclient/pymysql personally. Maybe I just need to distribute an example Python project with that setup to them.

I'm sure the global connection is fine, but the global cursor seemed to be a problem, because it gets .close()'d at some point.

Possibly for performance. mysql.connector is the fastest game in town, bar none. pymysql is my preference but it's a little slower, since it's pure python. SQLAlchemy is the slowest but most feature-rich and can be easier to use in some contexts. I used to use MySQLdb, the predecessor to mysqlclient, and I liked it a lot, but I transitioned to Python 3 and pymysql existed there but MySQLdb/mysqlclient did not, so I became a pymysql user.

Or probably they googled for Python mysql connectors and just picked one to start using

Macichne Leainig
Jul 26, 2012

by VG

QuarkJets posted:

I prefer passing around an open connection as a keyword argument and checking to see if it's still open before proceeding. This is easy to set up as a decorator that checks kwargs. Now all of your functions/methods can be easily decorated to reuse a common mysql connector that handles staleness without resorting to a global object.

That seems like a cool and good Pythonic way to solve that problem, I'll try to come up with some kind of "template" project that utilizes that method and try to explain to them how it's better that way. I feel like part of the problem is that the way they work it's just easy to code yourself into a corner, if I give them a good quality barebones project to work with I think they'll be more well set up for success.

Macichne Leainig fucked around with this message at 21:23 on Jul 16, 2020

NinpoEspiritoSanto
Oct 22, 2013




QuarkJets posted:

Possibly for performance. mysql.connector is the fastest game in town, bar none. pymysql is my preference but it's a little slower, since it's pure python. SQLAlchemy is the slowest but most feature-rich and can be easier to use in some contexts. I used to use MySQLdb, the predecessor to mysqlclient, and I liked it a lot, but I transitioned to Python 3 and pymysql existed there but MySQLdb/mysqlclient did not, so I became a pymysql user.

Or probably they googled for Python mysql connectors and just picked one to start using

Do you have sources for the performance gain? Connector uses the C API as does mysqlclient

Dominoes
Sep 20, 2007

An addendum to the duck type discussion. The merits of each approach depend on the details of the specific case. Pythonic (more generally language-idiomatic) code is an advantage.

This particular pattern is likely to lead to unexpected behavior at runtime, especially if you're processing external data. Be careful, or use a safer approach, eg one leveraging types.

Additionally, exceptions semantically imply something didn't go as planned, and using them to distinguish types feels confusing/obfuscating.

QuarkJets
Sep 8, 2008

Bundy posted:

Do you have sources for the performance gain? Connector uses the C API as does mysqlclient

I don't have them on hand, I found numbers some time ago while trying to decide if a new project should use something other than pymysql, which had become standard in a lot of my projects. I landed on "the performance differences aren't significant enough to use something other than pymysql".

Anything that uses the C API should be extremely fast, simple but pure python implementations are almost as fast, and higher-level APIs like SQLAlchemy were measurably slower but not enough to matter for most applications.

(iirc, Connector actually offers both a pure python implementation and a C API wrapper, and you can deliberately use one or the other)

QuarkJets
Sep 8, 2008

Dominoes posted:

Additionally, exceptions semantically imply something didn't go as planned, and using them to distinguish types feels confusing/obfuscating.

In this hypothetical example the exception block is explicitly handling something that didn't go as planned, and no type distinguishing is occurring. The function being written is expecting an object to have method or attribute X; that's the plan, and an exception is raised if that turns out to not be true.

Adbot
ADBOT LOVES YOU

Dominoes
Sep 20, 2007

Then it makes sense in this case.

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