Myths of Enterprise Python
paypal-engineering.com
paypal-engineering.com
Like all languages, Python has strengths and weaknesses, and there is no shame in that. An honest article would address the negatives head on, acknowledge them as potential negatives,(not skip around them) and provide alternatives, .
The strawman "Python has a weak type system" is a good example of such deflection.
No one (who understands type systems) would complain that "Python has a weak type system"
A more common "criticism" would be "Python does not have a static type system, which is handy for large codebases worked on by large teams".
Address that upfront, and you have a decent article. This is just a fanboy (who just happens to be at Paypal) praising his favorite language and ignoring its weaknesses.
Paypal is a large organization which needs to hire Python programmers. Everyone reading this now has a reminder that Python is popular at Paypal. We also know that endless PLT arguments are probably not common in the workplace.
Apple: https://developer.apple.com/swift
Facebook: http://flowtype.org + http://hacklang.org + http://hhvm.com
Microsoft: http://fsharp.org + https://haskell.org + http://typescriptlang.org
Mozilla: http://rust-lang.org
Google: The jury is out on this one.
In a previous HN discussion, I wrote to one of the Go designers:
> I disagree with you on the relative complexity of type systems, and, as someone passionate about my craft, I despair Go is merely good not great, due to what appears to be uninformed design decisions.
> You may prefer to write in Go, but you don't work in a vacuum. Your creation is out there, gaining mindshare, and propagating mistakes made half a century ago. As a language designer, you have the power to shape human thought for years to come, and the responsibility to remain intellectually honest. This is the meaning of Hoare's apology. He didn't know better. You have no such excuse.
"So, Go has message passing. Just like Erlang, since 1986.
Only without per-process heaps, which make crashing processes safe. And without process linking and supervision, which helps systems built using Erlang/OTP achieve nine nines of uptime. Instead, it includes null references, also known as Hoare's Billion Dollar Mistake.
But it's not enough to scorn the industry; Go's designers also look down their noses at academia.
A modern, ML-derived static type system? Generics, which would enable the unwashed mashes to write their own `append`? Ain't nobody got time for that — wait, what? Oh, Rust does?
Go's tooling is fantastic, and its pragmatism is commendable, but ignoring the last 30 years of programming language research is not."
Anyway, neither Dart nor Go is particularly "close to the hardware" as they both have fairly substantial runtimes. We're not talking about a macro assembler here, we're talking about a typed programming language. What the compiler does under the hood is largely irrelevant in any language that doesn't make a distinction between register, stack, and heap allocation.
> Simplicity-the design must be simple, both in implementation and interface. It is more important for the implementation to be simple than the interface. Simplicity is the most important consideration in a design.
http://www.matt.digital/comparing-c-nullable-types-and-swift...
Yeah, having done this before, it isn't that easy. You basically have to map NULL to something else, and if that mapping is so direct and straight forward, you actually haven't improved your engineering one bit.
A "billion dollar" mistake is a mistake Google can affod to make :-/
Even though they are enterprises, the term enterprise software often refer to the other companies, who use tech as an aid to run their main businesses.
Think about Box, MobileIron, and many such companies targeted to enterprises and who their consumers are. That is the enterprise software market.
I have not seen anyone complain that Python is not compiled for at least a decade, but maybe the author has.
I'm not worried about Python's type system. At worst it's manageable, at best it's expressive for prototyping.
But when I see benchmarks that suggest Python is 10 to 100X slower for critical server code, I have to wonder why anyone would use it for enterprise development.
Which is why there are so many Java and C++ code jockeys working in enterprise. Neither language is pretty or fun or interesting from a CS point of view. But there's no arguing both consistently run faster than anything this side of assembler.
I would have expected critical industrial infrastructure code to pay some attention to that - because speed isn't an abstraction. When you're running giant data centres, extra cycles consistently cost real money.
Dev costs are relatively small compared to operating costs. So it's well worth spending extra time getting good, fast compiled code working.
Because CPU cycles are cheap and bugs are not.
>Dev costs are relatively small compared to operating costs.
Uhh, not in my experience.
In that case, it may very well be the case that ops costs absolutely dwarf dev costs.
Similarly, it may be that what you want is to take data and run it through super-complicated algorithms depending on a lot of business data, and massage it all over the place... but you only need to do this 10 times per second. In which case your dev costs may absolutely dwarf your ops costs.
It's probably not possible to make a true statement out of context about which costs less. This depends quite heavily on what you're doing.
C++ does have its place (I'm not convinced about Java), but starting with it some project you could make as well with Python just because of performance isn't a good policy.
Because not all enterprise development relates to critical server code?
Neither language is pretty or fun or interesting from a CS point of view.
I find working with c++ brings huge amounts of fun, and I do that almost daily :P But maybe I don't have a CS view (not sure what that is supposed to be?)
[1] http://morepypy.blogspot.com/2015/02/pypy-250-released.html
FORTRAN is faster than C++ and Java but you don't see it used much in enterprise anymore...
> Strong typing: A type system that I like and feel comfortable with
> Weak typing: A type system that worries me, or makes me feel uncomfortable
http://web.archive.org/web/20091227121956/http://www.pphsg.o...
(Note that I wrote "weak type system", not "weak typing". "Weak" here is a just a generic adjective, and not meant to be precise.)
Because I don't believe you really, truly understand a language until you can tell me what sucks about it. It takes significant time (in a reasonably decent language) to discover the corner cases, performance bottlenecks, quirks, big-deficiencies-hidden-in-plain-sight and outright bugs in a language like, say, python.
Something as "rah-rah" this, which goes so far as to basically call the GIL a source of unicorns and rainbows, is convincing almost in inverse proportion to its stridency. Suddenly I'm wondering if all these "myths" about python might be smoke pointing toward a fire. That's probably a bit unfair, but it's hard to know what to take seriously when you're listening to a voice that's less than credible.
It's a good fanboy filter.
Because, really, it isn't just because a language has it's deficiencies that I would want to change that. That would probably result in a new language, which is not desirable. Usually a language is what it is because of it's pros, which unfortunately happens to create the cons. If you remove the cons you would probably also lose some of the pros.
So, I think a better question would be: "And what wouldn't you use [language] for? Why?" Or, if you want to sound cool, "What do you hate about it?"
edit: s/Java/Android Java/, unfortunately the spat between Oracle & Google has prevented most of Java 7 & all of Java 8 from being incorporated into Android Java, which is what I work with on a daily basis.
https://docs.oracle.com/javase/8/docs/api/java/util/Optional...
Still a library but at least it's part of the standard library.
Especially true of Lisps, of course.
""" :type member_list: list of [string] """
To have that hinting. I know this is getting better, but it isn't to the point of being very useful.
The GIL is definitely no source of unicorns and rainbows, but I think the case against it is usually overstated. There are numerous ways of sidestepping it (multiprocessing, pypy, C extensions, etc.), and it does serve a useful purpose.
That's definitely all true, but the article brushes it's implications for multithreaded Python off as if they don't exist, which is what one of the posters above me was probably referring to.
Yes you can do multiprocessing, but if I have lots of shared, volatile state that's not what I want. Yes you can use PyPy, but if that doesn't work for some python framework I use, or if I can't control my deployment environment and it only has CPython I can't use PyPy. Obviously you can write C extensions for about any language, using that as an arguments why the GIL is not a problem for multithreaded Python is disingenuous. Maybe I don't know or don't like to program in C? Green threads are not a substitute for multi-threading either, as they still don't allow full utilization of multiple cores and are really only a solution for I/O bound processing.
Of the 'numerous ways to sidestep the GIL' none are satisfactory if you have a CPU bound problem operating on shared state, that lends itself well to parallel execution, which are many. I wouldn't use Python to write a video codec or to do DNA sequence processing for example. It's not a fatal flaw for Python-as-a-language, but it's a flaw of CPython nonetheless, and not an insignificant one.
> Maybe I don't know or don't like to program in C?
If you want to write a video codec or highly performant multithreaded code, you should probably give it a go.
>Of the 'numerous ways to sidestep the GIL' none are satisfactory if you have a CPU bound problem operating on shared state, that lends itself well to parallel execution, which are many.
You mean exactly like the matrix calculations done in the C extensions of numpy?
(but it's a really promising project that all Python developers should follow!)
But this guy actually DOES try to argue it's a _positive_ somehow! He really is claiming it's all unicorns and rainbows, he doesn't mention _any_ negative to it, he says it doesn't effect concurrency at all, look at generators and deferreds that proves it (not true, a misdirection), he even tries to say it's a positive, the "GIL is a performance optimization for most use cases of Python, and a development ease optimization for virtually all CPython code. The GIL makes it much easier to use OS threads"
I think either this is an intellectually dishonest argument meant to confuse less-technical people, or the guy doesn't understand what he's talking about.
And I still think python is probably fine for 'enterprise', although as always it depends on what you're doing with it!
Yes, but pretending that you can have the ease of not worrying about thread safety while still having the performance benefits of multi-threading (real OS threads, mind you) is ridiculous. You can't have your cake and eat it too.
The language really excelled at small projects, where the expressiveness of the language and the excellent libraries available really let us get a lot done with little code and time. Avoiding the recompile/redeploy steps also helped.
But using the language for larger projects was quite a different thing. Suddenly you could find yourself in code several layers down, being passed an object of God knows what type from unfamiliar code, and having to find out what you were receiving essentially by trial and error. And once the execution times started to climb, it became increasingly frustrating to see trivial problems that would have been caught during compilation in a statically typed language appear in Python only after 30-60 minutes of execution.
There are surely ways to alleviate these specific problems -- I can think of some things to try myself -- but my experience suggests that the sweet spot for dynamic languages like Python is in projects that fit between one pair of ears, and stricter statically typed languages become increasingly useful as things scale up.
(Hardly a radical position, I know.)
But I think he overstates the case.
Calling Python "compiled" doesn't seem right -- he's more right that this doesn't matter, there's no reason not to use something because it's "not compiled".
Calling Python's typing "strong typing", eh, really? He provide a link to a wikipedia article on typing in general, how about a link to anyone else making the case that Python should be considered 'strongly typed', for a particular definition of 'strongly typed'? I'm dubious that it would be any definition of 'strongly typed' that those who think they want it... want. Again, I think a better argument might be: So what, you don't need strong typing for success, because of a b and c.
And the concurrency discussions is just silly. Sure, you can do _all sorts_ of things without multi-core concurrency, you may not need it or even benefit from it, and scaling to multi-process can sometimes work just fine too. But there are also _all sorts_ of cases where you do really want multi-core parallelism, and Python really doesn't have it -- and trying to justify this as "makes it much easier to use OS threads" is just silly. I guess it makes it 'easier' in that it protects you from some but not all race conditions in fairly unpredictable ways -- but only by eliminating half the conceptual use cases for threads in the first place (still good for IO-bound work, no longer good for CPU-bound work).
I think there's a reasonable argument to be made that Python will work just fine for 'enterprise' work. There are also, surely, like for all languages/platforms, cases where it would be unsuitable. By overstating the case with some half-truths and confusions, he just sounds like a fanboy and does not help increase understanding or accurate decision-making -- or confidence in the Python community's understanding!
Languages are often colloquially referred to as "strongly typed" or "weakly typed". In fact, there is no universally accepted definition of what these terms mean. In general, there are more precise terms to represent the differences between type systems that lead people to call them "strong" or "weak".
Static typing would be nice, but not in a Java or C# or C++ way. The extra verbosity makes it not worth the benefits. Sure, you get slightly more reliable intellisense, but at the expense of a program that's 15-20% longer.
>>> 1 + "0"
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: unsupported operand type(s) for +: 'int' and 'str'
This is what strong typing refers to. In [1]: 1 + 2.5
Out[1]: 3.5
In [2]: "foo" * 3
Out[2]: 'foofoofoo'
In [3]: [1, 2] * 3
Out[3]: [1, 2, 1, 2, 1, 2] In [1]: "foo" + 3
---------------------------------------------------------------------------
TypeError Traceback (most recent call last)
<ipython-input-1-21582e79f06e> in <module>()
----> 1 "foo" + 3
TypeError: cannot concatenate 'str' and 'int' objects
That's because the "special" method "__add__" implemented by the string class will raise TypeError if it gets any object that isn't an instance of a subclass of string.In a way it is kind of funny to call it, "strongly typed," but it does work. Maybe it should be called, "instancely-typed."
It seems to make 'strongly typed' pretty meaningless, and this definition is probably _not_ what anyone who says they want a "strongly typed" langauge is using, so it hardly counters them to say that python is "strongly typed" under another definition, it's just confusing them with semantics.
(Of course, the people who say they want 'strongly typed' may have no idea what they're actually talking about, but wouldn't it be better to educate them then to take advantage of their ignorance to push your pro-python agenda?)
In general, when someone is talking about strong typing, they are talking about silent failure for unintuitive or ambiguous constructs. For example, if the expression
x = '1' + 1
results in an error, you are probably using a strongly-typed language. In C, this is equivalent to x = 32;
In javascript you get x = '11'
In PHP you get x = 2
These are examples of weak typing.You could also describe Python's type system to be dynamic in that instances of the type meta-class define the constraints and objects (instances of a class) can have constraints added and removed at run-time. Python is still fairly strong in this regard in that the built-in classes are immutable (ie: it is a TypeError to assign a bound method to an attribute on a built-in class such as str).
I suggest "instancely-typed" because categories, unions, and type theory. I'm only coming to grips with that in that OCaml's type solver can be both awesome, annoying, and cryptic. And at the end of the day I'm still not sure what it's buying me other than proving exhaustive pattern matches in certain conditions, fast pattern dispatching, and requiring specialized operators (+, -, , / for ints... +.,-.,.,/. for floats... etc). I'm sure the enlightenment will come when it stops becoming such a PITA to write a basic program.
Sometimes not having to satisfy the constraints up-front makes exploratory programming (where the constraints are not specified and known up front) easier. Python is going the annotation route in newer versions of the language which is rather useful so that tools could be written to verify consistency up-front (or at least provide hints).
Otherwise, you'd run into Python's strong type system when doing an incompatible operation.
I particularly like Python's arbitrary-precision integers, where ints are implicitly converted to longs, allowing you to have the performance of ints without the problem of integer overflows.
I think the reality is "strongly typed" doesn't really mean much.
The interpreter/type system is doing nothing implicitly behind the scenes to coerce the objects.
As most OO languages, Python has function overloading based on the type of the parameters. The fact that those operators do different things when operating on different types is evidence that Python has strict types, not loose.
There is no dynamic dispatch based on types in the interpreter, you have to manually do it in the body of the method, of which you have one.
Python 2.7.1 (r271:86882M, Nov 30 2010, 10:35:34)
[GCC 4.2.1 (Apple Inc. build 5664)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>> 1/2.3
0.4347826086956522
>>> 1 / 2.3
fish: Job 2, 'python' terminated by signal SIGSEGV (Address boundary error)
(I didn't expect that last part.) Python 2.7.5 (default, Nov 3 2014, 14:26:24)
[GCC 4.8.3 20140911 (Red Hat 4.8.3-7)] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> 1/2.3
0.4347826086956522
>>> 1 / 2.3
0.4347826086956522
Identical output under Python 3.3.2Yep -- it seems like a readline problem. As you can tell, I don't use this machine for Python.
There are many popular and weakly typed languages in use today.
"[object Object]"
> {} + []
0
JS and PHP are the prototypical examples of weak typing.
1) It's meaningless--it's almost impossible to produce a real ranking of languages on the strength of their types.
2) These dynamic languages are all unityped because they're not statically typed. The fact that runtime tags won't allow certain operations to succeed has nothing to do with types.
3) Strongly typed is a rough and ready way of saying you don't do many implicit conversions.
I sympathize with (1). (2) is accurate, but really a terminological point. There's clearly a phenomenon to talk about, even if "typed" is the wrong word. I also sympathize with (3).
Python does far fewer implicit conversions than PHP, JavaScript or Perl. It even doesn't do at least one that Java does. So people often say Python is strongly, but dynamically typed. It's a real aspect of the language that you can view as a plus or minus.
These two statements conflict.
Python's proposal for type hinting will dampen the effect of type inconsistency I feel.
> type hinting will dampen the effect of type inconsistency I feel
I'm not sure that I see type hinting being that advantageous. I kinda hope that it could allow PyPy and other VMs to make assumptions that would otherwise require heuristics.
Perhaps type hinting could make static checkers/linters for Python more effective, though.
While there are a lot of concurrency options to not get you in trouble with the GIL, it is annoying that there is no canonical way or pythonic way of doing it. I saw people using things like monkey patching, which made my jaw drop. I had to implement Websockets recently and was totally confused as to the right way of doing it. I ended up evaluating NodeJS and Go for this function, and went with Go.
Overall ... I love Python. It is perfect for small projects. For larger codebases (3KLOC+), I am slightly skeptical. It can be done but developers need to have quality code and strong test coverage.
Our codebase at work is.. phew, I don't even know, a couple hundred thousand lines of Python? Still, easy peasy to dig into.
I will 100% agree on the websockets thing. Python is really failing in that area.
The project that I help maintain is a collection of Django apps totalling more than 700k lines. Thankfully I do not maintain all of it, but I am the primary maintainer for several sub-apps, totalling about 180k lines of Python. (This doesn't count the UI code, which is not in Python.)
I'm the sole author for about 12% of the part I maintain (since I wrote some of the individual sub-apps), and am familiar enough to describe probably half of the rest. There are still some parts that I really have to puzzle out ("What happens on the codepath to generate those reports?"), but that part shrinks over time.
The modular design that our original engineers used when they first built this system really helps, and the fantastic tooling in PyCharm is critical to my being able to navigate the codebase. Between grepping the python sources (thank god for shell aliases wrapping grep!) and my base familiarity with the system, I can start tracing with PyCharm's "find definition" to investigate things. Being able to run my own copy of the system, and put debugging breakpoints in (even in libraries!) is __amazing__.
Gets even easier when you use a code linter.
You had to implement Websockets in Python? Instead of using an already-functioning, tested library?
class WebSocketHandler(tornado.websocket.WebSocketHandler):
def on_message(self, message):
self.write_message("Echo: %s" % message)
I think the problem is that you chose a pretty heavyweight / complicated library.I know we can get picky about the exact characteristics of a languages type-system, but for me they fall into two camps: "Typeful" languages and "(effectively) Typeless" languages.
The former have a "good" typesystem, and expose it as a tool the programmer can use to help themselves solve problems. In the latter case, there may or may not be a type system lurking in the language somewhere, but the language either doesn't expose that system as a tool for the programmer to use, or it does so inconsistently.
Personally I think python is in the later camp, it has types but it doesn't really give the programmer much help when solving problems.
Clojure is another example. The Java type-system is down there somewhere in the murk, but idiomatic Clojure code doesn't use it, and it's not really a tool for the programmer to use, more an accident of the platform.
In python I would suggest wrapping your call in a try / expect block or using "isinstance()".
If you are using a publicly available library or popular piece of code that can return None or an Integer, I would argue that piece of code was written incorrectly. Newbie python users might do this, but I think experienced python devs would see the problem.
Finally, some documentation or justification for the reasoning behind this decision at the top of the function or on a web page somewhere would help as well.
As with most powerful , full featured languages it is pretty easy to shoot yourself in the foot if you are not careful, I don't think this is a python specific problem...
Better to check that the object you've been passed implements the interface you need rather than reasoning about its inheritance chain. Duck typing!
Minor pedantic correction: Python is dynamically typed, and strongly typed. Those are separate concepts.
Strongly-typed vs weakly-typed
Statically-typed vs dynamically-typedE.g. - as opposed to the Java practice of having 3 or more layers of fun to read (NOT!) XML on top of the language's native static typing to glue things together. I'm gonna be sick now...
https://msdn.microsoft.com/en-us/library/vstudio/ee461504%28...
It's not really dynamic typed, but has no requirements of making the types explicit, nor of making your functions work over a defined set of types.
If you're looking for a statically typed Python that can be grokked in a matter of minutes, and compiles down to a static binary like Go does, and runs as fast as C in benchmarks, you should definitely check out the Nim compiler [1].
Code example:
import rdstdin, strutils
let
time24 = readLineFromStdin("Enter a 24-hour time: ").split(':').map(parseInt)
hours24 = time24[0]
minutes24 = time24[1]
flights: array[8, tuple[since: int,
depart: string,
arrive: string]] = [(480, "8:00 a.m.", "10:16 a.m."),
(583, "9:43 a.m.", "11:52 a.m."),
(679, "11:19 a.m.", "1:31 p.m."),
(767, "12:47 p.m.", "3:00 p.m."),
(840, "2:00 p.m.", "4:08 p.m."),
(945, "3:45 p.m.", "5:55 p.m."),
(1140, "7:00 p.m.", "9:20 p.m."),
(1305, "9:45 p.m.", "11:58 p.m.")]
proc minutesSinceMidnight(hours: int = hours24, minutes: int = minutes24): int =
hours * 60 + minutes
proc cmpFlights(m = minutesSinceMidnight()): seq[int] =
result = newSeq[int](flights.len)
for i in 0 .. <flights.len:
result[i] = abs(m - flights[i].since)
proc getClosest(): int =
for k,v in cmpFlights():
if v == cmpFlights().min: return k
echo "Closest departure time is ", flights[getClosest()].depart,
", arriving at ", flights[getClosest()].arrive
Statistics (on an x86_64 Intel Core2Quad Q9300): Lang Time [ms] Memory [KB] Compile Time [ms] Compressed Code [B]
Nim 1400 1460 893 486
C++ 1478 2717 774 728
D 1518 2388 1614 669
Rust 1623 2632 6735 934
Java 1874 24428 812 778
OCaml 2384 4496 125 782
Go 3116 1664 596 618
Haskell 3329 5268 3002 1091
LuaJit 3857 2368 - 519
Lisp 8219 15876 1043 1007
Racket 8503 130284 24793 741
This language deserves your attention.If something is compiled to native code, what's the point of writing a library that's not just a binding? In python it makes sense, because you get the pure-python installation of your app - it doesn't depend on the OS, python versions, etc.
But once you're going to compile your app for a target platform... what's the point of not relying on C libraries?
Weak typing has its merits but sometimes static typing is very useful for reading and understanding code.
This is why I like dynamic languages that have immutable-by-default data structures, like Clojure.
Not saying it's not possible and doesn't work well for a lot of companies, but I do think you take on technical debt to get up and running fast when you choose Python. It's a choice I would personally think twice about.
This seems to be a better argument for statically compiled languages over dynamic languages rather than an argument against Python.
One thing that makes a difference between Python and other commonly used dynamic languages (here referring to JavaScript / ECMAScript and Lua) is that Python is dramatically more complex out of the box. This is both in terms of language features and Python's batteries-included standard libraries. For example, the amount of overloading that you can do in Python is very impressive, but the result is that common operations aren't necessarily predictable or dependable without more context (not that this isn't a problem in static languages - looking at you C++, but at least in the other languages you get type information to help out and some checking at compile time).
Same goes for Java, although in a slightly different sense. I've seen non-trivial Java projects balloon quickly where you have dozens or hundreds of classes & interfaces with no clear sense of structure. High line noise, lots of boilerplate. Sure it compiles but at the end of the day it's just as likely to hit a NPE so you have to rely on functional and unit tests regardless of static/dynamic/compiled/interpreted.
Obviously a lot of it comes down to who's writing the code. For me, a language that lets me succinctly express my intentions with minimal cruft is what wins.
I've seen shit java code as well. A lot of bad java code usually revolves around things not being modular or not having some form of consistent development patterns or not breaking methods down into simpler sub-problems -- I think documentation isn't as important as it is in python for the fact that I know exactly what is being returned, what exceptions can be thrown, and what exactly needs to be passed in just by looking at a method. In terms of the business logic associated with the class, that still needs to be documented.
That said, I understand why python is generally used at startups -- it allows fast initial development where at startups, time is critical. Long term development really relies a lot on the teams ability to make structured decisions and organize their code, which is a difficult task in any language.
Type errors tend to be very few and far between compared to logic errors.
Multiple processes in most web applications are best handled by a pre-forking webserver in front of something like mod_wsgi, and using an engine like Celery for asynchronous and long-running operations on the backend, often launched with something like supervisor.
I do take issue with some parts of the article, namely saying there is a good type system (there's not, but it's all fine, duck typing, etc) and that twisted is a good framework.
It is definitely true however that Python is a great fit for all kinds of serious applications, but with all things, it takes discipline.
Its so much more information that you need to load into your head.
To quote a picture from the post: https://www.paypal-engineering.com/wordpress/wp-content/uplo...
And its not like you need static typing everywhere just in some places its better to enforce it for your own sanity. Type hinting looks like a good way to solve this problem in python.
I imagine a statically typed Python dialect would only have an extra 15 or so lines, and the benefits would be numerous.
I love python as much as anyone, but having to keep a reference manual handy just to use someone's library because they had the audacity to use a variable is not my idea of a fun time.
EDIT: I'm probably exaggerating too much.
Would I use Python in a large, complicated, multi-developer project? Yes, I would. And my only real complaint would probably be that I like static typing so much that I'd miss it.
Actually you can have a statically typed Python if you want. Have a look at http://docs.cython.org/src/quickstart/cythonize.html
All type declarations are optional. It compiles modules to versions completely interoperable with the rest of Python code. They're importable, behave as you'd expect, etc.
I'm apt to screw up other things, but that's not one of them.
That's symptom of a bad typing system. I'm with a moderately sized Haskell codebase right now and type errors represent the biggest share of errors on it by a huge margin - several times bigger than runtime bugs.
Sometimes it's a win, other times it isn't.
NB I'm not being flippant - I've been using Python for a couple of years and appreciate the lack of boilerplate compared to many other languages and if there are "type" problems my unit tests, which I will be writing anyway, find them. Using an IDE like PyCharm does a good job of warning you about type problems at development time so I don't have a lot of run time type problems.
Static typing is like unit tests that take no maintenance.
> Type errors tend to be very few and far between compared to logic errors.
False distinction. If you just take your python code and write it line-by-line in another language, sure, you won't gain much. But if you actually work with the language, you turn logic errors into type errors. See e.g. http://spin.atomicobject.com/2014/12/09/typed-language-tdd-p... , and note that that's a lot more verbose than it would be in a modern language with type inference, higher kinds and so on.
And makes your code 20% longer, which makes for a lot of extra fun not-really-so-cost-free-after-all maintenance.
I found the complaint that it finds bugs earlier (at compilation time!) ironic given that, in my experience, running a suite of unit tests takes less time in python than, say, compiling does in Java, never mind compiling and running tests.
Just 20%? Sounds like a good deal, considering those that brag that brag that "over half of our code base are just tests!". I don't know if that kind of thing is fashionable or widespread any more, though.
Not necessarily true, especially if you are using a language with type-inference or you are able to encode your logic in types.
Additionally - what do you think unit tests are? They aren't additional code you have to write?
I'm not someone who thinks types completely reduce the need for testing, but I absolutely do not get why dynamic language fans are like "Uhg, I HATE having to write types", but then end up basically reimplementing a type system in a much more verbose testing framework.
I agree that it is not necessarily true, but the languages which manage to squeeze in static typing and still end up with programs that are shorter and sweeter than python's are all fairly niche right now, which carries its own set of problems.
>Additionally - what do you think unit tests are? They aren't additional code you have to write?
Never denied it for a second. There aren't any languages which don't require unit testing though, and there probably never will be. Let's not pretend otherwise.
>I'm not someone who thinks types completely reduce the need for testing, but I absolutely do not get why dynamic language fans are like "Uhg, I HATE having to write types", but then end up basically reimplementing a type system in a much more verbose testing framework.
I've never done this.
I'd wager that the amount of code I have to write, including tests, is less than in all other practical languages. Often much less. That is very valuable.
It would take a very gerrymandered definition of "practical" to say that Python counts but F# doesn't, and I'm pretty confident F# would win that comparison for most problems. (If you'll allow me Scala, which is my language of choice and the one I use full-time at my job, I'm very confident it would win the comparison for the vast majority of problems)
I also don't feel the amount of code I am writing to be all that significantly larger than what I was writing in Python/Ruby.
Less than that, in my experience. Certainly a lot less than the amount of tests and documentation you'd need to make up for the absence of types.
> I found the complaint that it finds bugs earlier (at compilation time!) ironic given that, in my experience, running a suite of unit tests takes less time in python than, say, compiling does in Java, never mind compiling and running tests.
You need to work with the language. Is a python test cycle faster than a full rebuild? Probably. Is it faster than the time between making a change and seeing the red underline in one's IDE? Absolutely not, in my experience.
Certainly more, in my experience.
>You need to work with the language. Is a python test cycle faster than a full rebuild? Probably.
By an order of magnitude.
> Is it faster than the time between making a change and seeing the red underline in one's IDE?
It can be that quick, yes. I have a unit test watcher that reruns them every time a file save in the project is detected (using watchdog/epoll), and I get the results back in seconds.
That has the added advantage of detecting more than just trivial type errors. It catches logic errors too.
One thing I've noticed on larger dynamic language projects: Developers tend to adopt a very defensive strategy in terms of validating inputs, to ensure it is clear a bug is not in their component. This includes a lot of what are essentially runtime type checks.
This is not necessarily a bad thing, because it ultimately makes the code more reliable. But it is "more code" which needs to be maintained, and eliminates the much of the advantage of using a dynamic type system in the first place.
Um, no. At best they are like a tiny fraction (and trivial fraction at that) of the unittests required. AND static typing often requires maintenance (as all code does) including initial burden of creating them in first place.
> Type errors tend to be very few and far between compared to logic errors.
The divide between type errors and logic errors is entirely dependent on the language and the discipline/inclination of the developers. In some languages, what you might think of as "logic errors" can easily be moved to "type errors". And in that regard, the difference between what is unit testable and statically typeable is also entirely dependent on the language and the discipline/inclination of the developer. So what might have to be expressed as unit tests in one language, might be checked by the static type system in another language.
But I can understand how some people might think that static type systems are only for catching things like "error: expected addition of integers, but got attempt at adding an integer with a FireTruck". ;)
More restricted languages, e.g. Java, do have advantages in terms of forcing developers to do some more self-documenting and better opportunities for tools to help with syntax highlighting, refactoring, and warning about those errors you mention. But those errors are usually caught easily even with basic test procedures and almost always if there's a half-decent automated testing regimen.
A lot of it comes down to, who's writing this big project? If developers are talented, there's a lot to be said for the freedom granted by a language like Python or Ruby. If developers are more mediocre, the forcing function of a language like Java may help to produce a "boring" and larger but understandable code base.
This is a bit of a false dichotomy.
Much like I don't think lisp is popular for its functional-ness or whatnot, I don't think python or ruby are popular for their dynamic properties. My guess is that 90% of it is just how the code ends up looking. And with type inference getting further along, I think we'll see more people realizing that typing is a great sanity test to have in your code (especially in big codebases). See the popularity of Go in pythonic circles.
I have never been shown any non-tiny piece of robust code that was easier to deal with because of a language's dynamic nature. I have been on this Earth a bit less time than others, but my gut feeling is that it doesn't actually exist.
(note: my day job involves a lot of python, and I love the language for many things. I am looking forward to optional type annotations, though, as are many of my coworkers)
"...There are around 5,000 developers using [Python] at Bank of America, .. there are close to 10 million lines of Python code .. and we got close to 3,000 commits a day."
IMHO, it would be scary with any language.
The main problem isn't anything to do with technical failings of the language, but a misconception that it's an obscure niche language that nobody uses outside of academia, with an ecosystem bordering on the nonexistent. People seem to think that if you start using Python you're going to end up with an incomprehensible codebase that's impossible to maintain because you can't hire developers who know it. They're generally quite surprised when I tell them how widely used it is and what all it gets used for.
I can almost see these guys' angle, of why they might see this as a possible threat that could undermine their career. .NET coding pays well, and is usually semi-exclusive to those who previously had an employer pay for them to use the tools, even though that's not theoretically necessary.
Someone I know does a math and economy study and they use some programming to find optimal solutions for certain problems (e.g. traveling salesman). They are taught C++ with pointers and by-reference parameters and OOP and everything in a 7 week course. Why not Python with some functions? That perfectly suits their purposes and makes life a lot easier both for the teacher (less code to check; clearer code) and the student (easier to learn; less code to write).
For other computer science topics, probably not.
Hmm perhaps if you are interested in the technical working of a data structure, but even if you use Python you'll have to mind your memory and CPU usage. They have to implement things like the traveling salesman problem and get the correct answer to a reasonable number of cities.
Python is slower than machine code by definition, but not so much that it becomes much harder to do the same calculation. They have to think of speed regardless of the language, and doing that is much easier when you pass around lists instead of pointers to pointers of doubles (double * *, added spaces to avoid markdown).
Disclaimer: .Net developer learning python/django for a rather large-scale cloud implementation.
You see it in spades in the Silverlight community. They're all blaming Microsoft for the decline of Silverlight, even though it's largely due to factors outside Microsoft's control.
Python2 to 3 migration is not easy. There are tools but the problem is that they don't see everything and therefore, you end up with 95% of your code converted. Then it's up to you to figure out the last 5%, which is an order of magnitude harder that the first 95%... So I ended up having a fairly long transition of migrating Python2 code to Python2+3 code.
For bothe these issues, the common discourse is : have proper test coverage. But well, we live in a real world, and maintaining a code coverage strong enough to allevaite the problems (around 90%) is just very hard. If you're coding alone, that may be just too much (my case). In a team setting, with money to spend, that may be possible, but you'd need a very disciplined team.
But anyway, AFAIC, working with Python is just super productive (I compare to Java). It also feels much more battle tested than, say, Ruby.
For me python is not a scripting language but a "glue" language set in the middle of a huge libraries ecosystem.
Now, I didn't do XA transaction stuff, high performance stuff, etc. For me it's more alike a well done Visual Basic : you can achieve a lot very quickly. Contrary to VB, the language and its ecosystem are really clean.
I'm lovin' it
Looking back, I don't think even for a personal project, I would ever do something that wasn't a one-off without good test coverage. It's essentially taking on technical debt, as it makes you much more afraid of fixing anything.
I do as well, and I find that while we occasionally run into typing bugs, the tests nearly always catch it and they catch it quickly. Moreover, these are tests that we'd write in any language, and static typing would, in most other languages, mean more verbose code. Overall we still come out ahead.
>However, when you end up with meta code, then it can become really difficult to track the types down in the n-th level of recursion...
Yea, I try to avoid that. If there's a library that does meta-code that's unit tested to hell and back, maybe. If I have the time to write one and unit test it, maybe. But, I still try and keep regular projects clear of it.
There is also another library out there which approaches the problem a bit differently
Statements like "Python is more strongly-typed than Java" can mean too many different things without a precise definition of what "strongly-typed" means. The Wikipedia page linked from the article even supports the position that there isn't an accepted definition for the strong vs. weak! (https://en.wikipedia.org/wiki/Type_system#.22Strong.22_and_....)
These terms are not very illuminating, and I don't understand the post's argument about types as a result, especially w.r.t None vs. null.
One argument that the post might be making, and I'd like to see fleshed out, is "Python's expressions and built-in operators check their inputs at runtime in a way that gives useful and effective error messages in practice." That seems like a lesson from experience that could be backed up with anecdotes and provide some useful feedback on the language. That avoids the terminology debate about types, which is more about picking definitions than about the quality of the language for certain purposes.
It does require defining "useful and effective" for error messages, but I'm more interested in that debate :-)
Also Python is good at thing but
> feel comfortable using python for serious, well designed projects that scale and do every and any thing that a person may want or need
Might be a little to bold of a statement :)
Edit: the "Python 3 Wall of Superpowers"[1] is a good resource for seeing how far the ecosystem's conversion to Py3k has come. Many of the "red" packages even have Python 3-compatible forks (e.g., Supervisor).
I periodically check my requirements.txt's and there's still a few big holdouts left.
I know that python3wos is out of date regarding the libraries people actually use. When I look at the py2-only libraries on there, I see:
- the big "legacy dependencies", Twisted and gevent
- libraries that are ported but the site doesn't know it, such as protobuf
- highly specific code to extend a particular system, such as tiddlywebplugins
- system utilities that it doesn't matter what language they're in, such as supervisor and Fabric
- libraries that have been abandoned (in all versions) and superseded, such as MySQL-Python
I'm not saying you're wrong, I'm saying that we need a better python3wos. It makes it look like "unless you bet on a massive legacy asynchronous framework, you're fine".
I think that to some extent this should be the case, but to some extent, there are things that should be ported that we're not seeing because of the unrepresentative set of packages on python3wos.
Honestly, if there were some big incentive at this point I would go through the hassle of upgrading, but there isn't. The gains on python 3 seem relatively minor and incremental.
Python 3's library is growing all the time and in my opinion already has all the libraries or bindings you'll need right now.
Which tools? I use python for scientific computing and I can't think of any tool that I use where the python 3 version (if it exists) is newer/better than the python 2 version.
Newer and Better is a totally different question and this is why we have the Python 2 or 3 debate.
Python 2 gets many of Python 3's features back-ported (they can be enabled with an import statement), which is really convenient when working with 2, but it also helps contribute to the lack of a migration from 2 to 3.
Python 2 and 3 are very similar though, and most projects can even run under either 2 or 3 with the exact same codebase. So it doesn't take much effort (or none at all) to move a project from 3 down to 2 while still in early development if requirements necessitate.
[0] One example that comes to mind is a difference in the way str.format() works. In Python 3, strings are unicode text objects, in Py2, they are bytestrings. Some projects used str.format() in Py2 to format binary data rather than text, which breaks when moving to 3. Porting a compatible change to Py3 has been rejected several times because of the complexities in implementation, as well as it being unidiomatic to the language. See:
For the rest, it depends on the libraries you need...
Google actually just started supporting Python 3 last week, and they were one of the last big holdouts.
You have to understand that these articles are written for a number of reasons:
* The company (here, paypal/ebay) needs to recruit people.
* Often, the language or technology is under siege internally, and these external posts strengthen its position.
* The company wants to get some message out there, but it doesn't actually have any interesting technology of its own, so it goes on and on about some known tech.
I was using the Requests library last night to work with some APIs, it's an absolute gem, it's so easy to use. The Python library manager (pip) just works and the idea to isolate your dev environment with virtualenv is fantastic. PEP8 for a universal style guide is underestimated in large projects.
Python really needs to step up the game to stay ahead of up and coming languages like Nim, which looks like this:
import rdstdin, strutils
let
time24 = readLineFromStdin("Enter a 24-hour time: ").split(':').map(parseInt)
hours24 = time24[0]
minutes24 = time24[1]
flights: array[8, tuple[since: int,
depart: string,
arrive: string]] = [(480, "8:00 a.m.", "10:16 a.m."),
(583, "9:43 a.m.", "11:52 a.m."),
(679, "11:19 a.m.", "1:31 p.m."),
(767, "12:47 p.m.", "3:00 p.m."),
(840, "2:00 p.m.", "4:08 p.m."),
(945, "3:45 p.m.", "5:55 p.m."),
(1140, "7:00 p.m.", "9:20 p.m."),
(1305, "9:45 p.m.", "11:58 p.m.")]
proc minutesSinceMidnight(hours: int = hours24, minutes: int = minutes24): int =
hours * 60 + minutes
proc cmpFlights(m = minutesSinceMidnight()): seq[int] =
result = newSeq[int](flights.len)
for i in 0 .. <flights.len:
result[i] = abs(m - flights[i].since)
proc getClosest(): int =
for k,v in cmpFlights():
if v == cmpFlights().min: return k
echo "Closest departure time is ", flights[getClosest()].depart,
", arriving at ", flights[getClosest()].arrive
And performs like this: Lang Time [ms] Memory [KB] Compile Time [ms] Compressed Code [B]
Nim 1400 1460 893 486
C++ 1478 2717 774 728
D 1518 2388 1614 669
Rust 1623 2632 6735 934
Java 1874 24428 812 778
OCaml 2384 4496 125 782
Go 3116 1664 596 618
Haskell 3329 5268 3002 1091
LuaJit 3857 2368 - 519
Lisp 8219 15876 1043 1007
Racket 8503 130284 24793 741
http://goran.krampe.se/2014/10/20/i-missed-nim/And the person in security hat now says: so how do you deal with library upgrades? If you need to go back to original app developers to provide you with a new version just to update one library, then you've got a problem.
It's controversial statement.
Generators, greenlets, deferreds, and futures, it's all not great concurrency primitives definitely. It's okay for typical "python" tasks, but many applications have needs in more powerful solutions like golang channels for example.
Channels can be instantiated, goroutines cannot.
Correct me if I'm wrong please.
In the world of concurrency you could probably even call goroutines an abstraction but goroutines are at least closer to the fundamental concurrency primitives such as threads, locks, mutexes and tasks/coroutines/whatever.
"Our most common success story starts with a Java or C++ project slated to take a team of 3-5 developers somewhere between 2-6 months, and ends with a single motivated developer completing the project in 2-6 weeks (or hours, for that matter)."
Or, they aren't actually deriding Python for the GIL, they are noting that, given the GIL, you need to use an evented approach, so you might as well use a platform designed for that as its central model, rather than one that's designed around the threaded model but without the ability to use it effectively.
I get the impression that most web devs wants to keep up with the latest tech, and by most counts Python is old now.
No, because Python with Twisted isn't the same as a platform built for the evented model from the ground up, its a library for a traditional threaded platform built to handle the evented model.
> I get the impression that most web devs wants to keep up with the latest tech, and by most counts Python is old now.
I don't think the desire of devs to be working in something that they perceive to be in demand and growing moreso is restricted to web devs.
As for PyPy's "faster than C" performance, people really really really need to stop believing anything about a JIT running a single tight loop that exercises one f'ing line of code! Follow that link and tell me if your code even remotely resembles that code. In practice, PyPy is, I believe, "faster than CPython" with a lot of caveats still, but "faster than CPython" isn't a very high bar.
(Similarly, though another topic, Javascript is not a "fast language". People seem to believe this partially because of JIT demonstrations in which integers being summed in a tight loop runs at C speed. But this is easy mode for a JIT, the base level of functionality you expect from one, not proof that the whole language can be run at C speeds.)
There is no version of Python that will run you at anything like C or C++ or Java or Go or LuaJIT speeds on general code. It can't; for one thing you have no choice but to write cache-incoherent code in Python, to say nothing of the numerous other problems preventing Python from going fast. (Copious hash lookups despite the various optimizations, excessive dynamicness requiring many things to be continuously looked up by the interpreter or verified by the JIT, etc.)
I've drilled down on this one, but there several other "debunkings" here that are equally questionable. Python does not have a "great" concurrency story... it has a collection of hacks of varying quality (some really quite good, though; gevent is awesome) that get your around various issues, at the cost of some other tradeoff. The definition of "strongly typed" that Python conforms to is almost useless, because everything is a "strongly typed" language by that definition. In practice, it's a dynamically typed language, and yes, that can cause problems. Another collection of hacks are available to get around that, but they're add-ons, which means the standard library and other libraries won't use or support them. Yes, Python is a scripting language, it's just that it turns out "scripting languages" are a great deal more powerful that was initially conceived.
Wow, I must hate Python, huh? Nope. It's a fantastic language, certainly in my top 3, and still probably underutilized and underrespected despite its general acceptance. When I hear I get to work with it, I generally breath a sigh of relief! It is suitable for a wide variety of tasks and should certainly be in consideration for a wide variety of tasks you may have to solve.
But, it is always bad advocacy to gloss over the problems a language has, and all languages have problems since no one language can solve all problems perfectly. If you are doing something really performance sensitive, stay away from Python. If you've got something highly concurrent, think twice... your problem needs to comfortably fit on one CPU using one of the existing solutions or there's hardly any reason to prefer Python. (Yes, Python can sort of use more than one CPU but if you're going to do that you'll probably be happier elsewhere. "Just throw lots of processors at the problem" isn't generally a good solution when you're starting from a language that can easily be ~50-100x slower than the competition... that's still an expensive answer, even today.) Yes, it is dynamically typed and there are situations where that is OK and situations where it is counterindicated. In the long term, you don't help a language by trying to minimize the problems... you help by making it clear exactly what it is good for, when you should use it, and when you shouldn't. Otherwise, you convince a hapless programmer to pick up your solution, pour a year or two into discovering it doesn't actually do what you said it did, and now you've made an enemy for your language. Better for them to never pick it up because you truthfully told them it wasn't suitable.
That said, though, be sure your task is performance sensitive before just writing Python off... modern machines are really hard to understand the performance of and most people's intuitions are pretty bad nowadays. Dynamic typing has its problems, but so does static. Etc. etc. No easy answers, alas.
I agree on the rest, though.
Edit: since a lot od people here are arguing what does 'strong typing' mean, I take it from what I learned at college: it means that, apart from typical conversions (like int -> float), it doesn't do many automatical conversions for you.
I've had projects fail cause of not getting done, being buggy, but never for not being fast enough.
Finally, slowness, until you get really low-down is relatively easy problem with many solutions.
"Finally, slowness, until you get really low-down is relatively easy problem with many solutions."
There is a barrier that you can hit in Python/Perl/Ruby/Javascript where you're trying to do something, you've optimized the Python/etc. to within an inch of its life, and it's still just too slow. I've hit it twice now in pretty serious ways. Once you've removed all the slowness-that-has-easy-solutions, you're still using a very slow language... the 50-100x number I cite is with the slowness already removed for optimal code, though, to be fair, this is in comparison to fairly optimal C/C++ as well. Well-written Python can be competitive with poorly-written C, and that is also not even slightly a joke, since it's generally easier to get to the well-written Python. But you can still run out of juice on a modern machine.
But ultimately this is just something you want to know and understand, and not be too bedazzled by claims that everything's hunky dory in every way.
There is a solution from Twitter that my devops team has been flirting with called PEX[1]. It builds all of your dependencies into a zip file similar to a jar and sets it up to work by just putting it on your pythonpath. This would in practice be very similar to an uberjar.
The real complexity comes elsewhere - both in java and python world, setting up the java application server or wsgi server for python is more involved than just dropping an app there. And then there comes the debugging the exceptions... there I would pretty much prefer the python world.
Also, be careful with zipping python projects. While .zip is a valid member of pythonpath, packages can have problems with finding their assets (if they have any). For example, you cannot zip django this way.
[1] It even handles setting up vcvars when building native extensions. I was impressed, it was easiest building of windows binaries for free software I've ever seen.
For builds: - build a conda environment for your project - export your conda environment using conda list -e, and then take all the conda packages for those and put them into a single tarball
For deployment - bootstrap a base python environment using miniconda http://conda.pydata.org/miniconda.html - install that tarball of packages with conda install <mytarball.tar>
It's not as simple as a jar, but it's reasonably close
Our stack in Crowdcrafting is fairly simple in terms of hardware (we've two servers with 2 GB of RAM each and only 2 cores, while the DBs have 4 GB of RAM with 4 cores). You can read more about it here: http://daniellombrana.es/blog/2015/02/10/infrastructure.html
In my experience the problems that we've had are always related about how we develop, not the technologies. One of our ways of solving problems is avoiding increasing the resources of the hardware as it will "hide" the real issues of your software. Thanks to this approach we were able to store more than 1.5 records per second over a period of 24 hours in 2014 with a DB running on less than 1GB of RAM and our servers with 2GB of them. It worked really well! (Actually after that our provider called us to expend more on our hardware).
Our platform is designed to scale horizontally without problems. We use a very simple set of technologies that are widely used, and we try to use very simple libraries all the time. This has proven to us to be very efficient and we've managed to scale without problems.
We heavily test and analyze our software. This is mandatory. We've almost 1000 tests written covering 97% of our code base. We also analyze the quality of our code using a third party service and we've an score of 93%, and this helps people to help sending patches and new developers joining the platform.
Right now our servers are responding in less than 50ms in average, and we are not even using Varnish (check out this blog post: http://daniellombrana.es/blog/2015/03/05/uwsgi.html). Thus, yes Python is a good language, it can scale, and if you usually have a problem it will be basically in your own code. Hence debug it!
Cheers,
Daniel
And for the record, by Enterprise I'm not talking Silicon Valley Enterprises. These are strictly non-tech Enterprises that traditionally view anything software related as a cost center.
We're engineers here so let's be real and recognize that different tools are suited to different tasks. Limiting oneself to concurrency without OS threads is, to be polite, not necessary. Obviously you CAN build pretty much anything you want with pretty much any tool, as the examples in this article show, but that doesn't mean you should.
(written by someone who writes Python daily)
My hope is for some day Matlab to be as obsolete as Octave itself.
edit: (I know a boatload of different languages - Java is the most comparable and least shocking for developers who aren't FP nerds. Go is inadequately expressive.).
If only... In actuality, the majority of python's package management is being redone by pypa, and it's not complete.
That's been my biggest problem with python; the circuitous path to deployment the Right Way in an enterprise, where one doesn't simply publish to pypi.
It'll get there, but to throw around the word "excellent" hides a lot of the current pain.
Secure Connection Failed
An error occurred during a connection to www.paypal-engineering.com. Cannot communicate securely with peer: no common encryption algorithm(s). (Error code: ssl_error_no_cypher_overlap)Ok, Python is a fine language, even for building large-scale systems. No, it is not free from drawbacks.
#1 : Ok, Python is not new and is mature #2 : "Compiled" is almost a meaningless word. The general definition of compiler is a program that transforms a document written in a source language into a document written in a destination language. TeX is compiler, a CSV to XML parser is a compiler. As regards security/reverse engineering, Python and Java bytecode files can be very easily decompiled into the original program. It is not the case for C/C++ and thus reverse-engineering is much more difficult. Anyway, this issue can be mitigated using obfuscation. So ok for this myth. #3 : Again speaking about the "security". I don't see why Python would be more "secure" than Java. I can see why it would be more secure than C/C++(runs on a virtual machine, so less buffer overflows, bounds checking etc.).
#5 : Yes very valid point for Python. And then you start comparing the JVM (a platform, a runtime, a virtual machine) with Python (a language). This is like comparing apple to oranges. And no, Java is not dynamically typed. Python is.
#6 : This is the wrongest point of your article. Python is slow, very slow. Excuse me, CPython, the runtime that virtually everyone uses is very slow (as all non-JIT virtual machines). Usually 5-10x slower than a native program and 2-4x slower than a JVM program. You can't completely decorrelate the language and the platform. Speaking about Java performance means discussing the JVM (although Java can be compiled). Speaking about Python means discussing CPython.
Performance-wise, Jython is not much better (and sometimes a lot worse than) CPython, and they only implement Python 2.5. Pypy does an excellent job at optimizing Python and often yields on par performance with the JVM. However, it is incompatible with C extensions/modules written for CPython, which means it can rarely be used in production (goodbye databases etc.)
There are countless stories in HN of start up developers rewriting their systems from Python/Ruby to Java/Go because performance was an issue.
#7 : I think some of your examples are contrived (e.g. Youtube) as we don't know where exacly where Python is used is the infrastructure. I only use Python to draw graphs does it mean my infrastructure relies on it ?
About GC pauses. Yeah, there are no pauses in Python because the GIL allows only one thread to run concurrently.
#8: The GIL is a performance optimization ? Really ? The GIL is here because it eased the development of the CPython VM but is terrible for performance. Because of the GIL a CPython cannot run more than one thread concurrently. In the era of multicore processors, this is terrible for performance. Yes, there are workarounds for I/O operations (greenlets etc.), but for processing intensive tasks, it is impossible to exploit a multicore processor with Python. And no multiprocessing is not a solution, as it does not allows to share memory between processes. Also remind that Python is often 4x slower than Java on a signle core...
#9: True but this looks like a strawman. Nobody ever said Python programmers are scarse.
#10: I am not having this debate again, but a strong type system is useful for big projects. I don't say it's mandatory but it reduces development time.
You actually can. multiprocessing defines a few classes (e.g. Array) that store their data in a mmap kept in the module. Data there will be visible to all processes, and you can even have a numpy array as a view to this data.
That said, my attempts at working with this recently have been pretty painful. multiprocessing tries, but at least in Python 2.7 does not succeed in abstracting away the differences between Unix forks and Windows spawns. This results in a lot of weird issues: things running differently in command line vs. console IPython vs. IPython notebook; the need to structure your code to avoid pickling errors; etc. This is probably the biggest portability issue I've encountered with Python thus far (using it mostly for scientific problems.)
I'm aware that there are solutions to some of these issues out there, but it's too bad that the standard library implementation has these issues.
Besides, there are way better links for pro-Python arguments. I would point to Norvig's spell-checker in 21 lines of Python for example (http://norvig.com/spell-correct.html).
https://www.python.org/dev/peps/pep-0484/ http://baypiggies.net/
Giving a large number of "enterprise" developers a language like python means that you end up with ~10m lines of poorly designed, un-pythonic mess.
My personal opionion is that using python for any kind of large scale infrastruture is a very bad idea.
Also, library support still isn't 100% there. So, if one critical piece of your stack isn't on 3.x, you've gotta throw out the whole thing that stick with 2.x.
That said, if I were starting out now, I'd start with Python 3.
When we talk about compiled languages, we usually mean "compiled to machine code". It's wrong to put a non-JITed "compiled to bytecode" language in the same category as C/C++/Haskell/Rust/Nim/etc.
> Furthermore, CPython addresses these issues by being a simple, stable, and easily-auditable virtual machine.
http://www.cvedetails.com/vulnerability-list/vendor_id-10210...
> Each runtime has its own performance characteristics, and none of them are slow per se.
Unfortunately, they all are slow when compared to the most efficient language/compiler available on the same platform. And no hand waving will fix this. Nor the small and not so small differences that render non-CPython implementations unusable in practice. The only valid argument remaining is that not all programs are CPU bound, but how many Python programmers are willing to say "I can only write non CPU-bound software in this language"?
> Having cleared that up, here is a small selection of cases where Python has offered significant performance advantages:
> Using NumPy as an interface to Intel’s MKL SIMD
The fast parts of NumPy are written in C. Python doesn't get to claim any performance advantage here.
> PyPy‘s JIT compilation achieves faster-than-C performance
I doesn't, they are just comparing different algorithms.
> Disqus scales from 250 to 500 million users on the same 100 boxes
Yes, thanks to Varnish that caches those slow Django requests, according to the linked article. Can you guess what language is Varnish written in? In the mean time, Disqus has also moved its slow as hell services to Go: http://highscalability.com/blog/2014/5/7/update-on-disqus-it... (a case where a shitty compiler that produces machine code beats a bytecode VM by so much it isn't even funny).
> It would be easy to get side-tracked into the wide world of high-performance Python
This depends on what you're smoking.
> One would be hard pressed to find Python programmers concerned about garbage collection pauses or application startup time.
Not garbage collection pauses, but in more than one occasion, when doing data migrations with processing done in Python, I had to call gc.collect() manually each N iterations to keep memory usage under control.
> With strong platform and networking support, Python naturally lends itself to smart horizontal scalability, as manifested in systems like BitTorrent.
The BitTorrent library of choice nowadays is http://www.libtorrent.org/ - written in C++.
> The GIL makes it much easier to use OS threads or green threads (greenlets usually), and does not affect using multiple processes.
The devil is in the details. You can only run OS threads in parallel if only one of them is Python code. To parallelize multiple instances of Python code you need to start multiple instances of the Python interpreter. Or you can pretend that you don't really need parallelism after all and cycle green threads on the same core while bragging about millions of requests per... day.
> Here’s hoping that this post manages to extinguish a flame war [...]
:-)