Some things that should be easy are ridiculously hard in Python. Regexes for one have a horrible API story. Another one is the import system which I view as a totally broken effort to heal self-inflicted complexity with more complexity. Here is the code I came up when presented with the task to import a module when its name is given:
Details may change any time without notice. The complexity here is a consequence of Python's design decision to treat module names as identifiers, not as quoted strings. The import system is full of such poor choices (dot/relative imports, `__init__.py`, `*.pyc` / `*.pyo` files littering one's source directories, and so on)
Agree on regex. I started in perl many years ago and loved how integrated regexes were. Was appalled that was was a simple one liner in perl turned into multiple lines in python for every regex.
Making a powerful tool easy to use means it will be used more.
It would be nice if that flaw could be fixed, as I like coding in python in general
count = 0
t1 = time.time()
for line in open("nucleosome.pdb"):
if line =~ m/(ATOM |HETATM)/:
count += 1
print count, "atoms in", time.time()-t1, "seconds"
It used it own PLY-based parser to generate the Python AST.
I realize now how much of a hack it is. The portion 'm/(ATOM |HETATM)/' could be part of valid Python expression, as:
>>> ATOM = HETATM = 1
>>> m = 2
>>> m/(ATOM |HETATM)/1
2.0
so either m// is enabled only after =~, or there has to be some way to recognize the lexically correct match term -- something more powerful than the "m/[^/]*/[a-z]*" used here.
I have to say I really like Python's module system. Modules as objects, scoped import by default and filesystem-backed module resolution (+sys.path) are all good choices in my opinion. Cosmetic warts like __pycache__ are unfortunate, but not deal-breakers.
My main memory of perl (I used it for CGI and local CLI tooling back in the day) was that it was usually very terse, to the point of being a write-only language. I learned an important lesson with it: the more clever you feel writing code, the more you are likely to hate maintaining it after a few months away!
There was a long time period (IMHO good few years in early 2000s) where Python looked better on paper but Perl was still better for production.
All the Perl libraries for doing certain things (db access, web stuff, process management) were "actually battle tested" and worked well even if they were utterly unreadable. Python looked a lot nicer but when you tried to do any real work with it everything seemed to leak memory or give you continuous paper cuts - and it was a lot slower.
I made the switch to Python eventually but it took a while.
That tallies with when I was using Perl (late 90s / early 00s). Python was very much on the up in that time but I didn't feel compelled to switch, then DayJob and personal projects took me away from such thing completely (DayJob was Windows/VB6/IIS/ASP based, home web stuff went PHP for a while and admin stuff to Bash).
The problem for me with logging is that it's slow for production code:
Python 2.7.15 Linux (logging is 60x slower):
[root@hbtest ~]# py -m timeit -s 'import logging' "logging.info('something happened')"
1000000 loops, best of 3: 1.31 usec per loop
[root@hbtest ~]# py -m timeit -s 'import sys; debug = False' "if debug: print >>sys.stderr, 'something happened'"
10000000 loops, best of 3: 0.0216 usec per loop
Python 2.7.15 OSX (logging is 71x slower):
$ py -m timeit -s 'import logging' "logging.info('something happened')"
1000000 loops, best of 3: 0.925 usec per loop
[jim@mbp hbrel]$ py -m timeit -s 'import sys; debug = False' "if debug: print >>sys.stderr, 'something happened'"
100000000 loops, best of 3: 0.013 usec per loop
Python 3.6.8 Linux (logging is 99x slower):
[root@hbtest ~]# python3 -m timeit -s 'import logging' "logging.info('something happened')"
1000000 loops, best of 3: 1.62 usec per loop
[root@hbtest ~]# python3 -m timeit -s 'import sys; debug = False' "if debug: print >>sys.stderr, 'something happened'"
100000000 loops, best of 3: 0.0163 usec per loop
And, as usual, Python 3 is 25% slower than Python 2 for the logging case (but 2x faster for the noop if debug case). I hope the recent efforts to increase Python 3 performance are successful.
Oh you want to print to stderr hmm?