It is a habit that you pick up after working with Python for a while. I hate to say it but it is a good habit. As a C/C++/C# programmer for a long time, I have been brought up with the "curly braces" mentality. We learn it in school, we do it at work, we read it in other people's code. If you look at C/C++/C# code, you will see that programs tend to extend to pages and pages of code. But they don't do much since most of the pages are dedicated to whitespace. Sometimes it takes reading 2 or 3 pages (scrolling if you use an editor) to actually finally learn that this block of code does this (in one sentence). Urghh.....
I am currently porting a C# .NET application to Linux C++ for Intel. There is reams and reams of legacy C# code to wade through. Corresponding there is so much whitespace to slog through before you can figure out in your mind what it is doing. It is a process. It is work. But it is so unnecessary. I now refer to one item in the Zen of Python: Simple is better than complex. This little diddy should apply to all languages as well.
It's the "curly braces" that add so much whitespace. It is these necessary habits which we learned in school and in practice. Maybe it is time to unlearn them. I don't know if other C/C++/C# developers out there feel the same. So much of our work is wading through complexity. It keeps us busy but sometimes I wonder if we should stop and ask: "is all this complexity really necessary?"
I have been diving a little into the world of Jython. This is another example of the usefulness of Python as a glue language. This little snippet of code shows how to reuse custom built Java JAR libraries without having to add too much code. It also demonstrates an example of simplifying the process of generating Java listeners and connecting them.
import sys class MDFDrv: def __init__(self): sys.path.append(r'C:\sdk.jar') def accept(self, event): print "Accept called" def reject(self, event): print "Reject called" def unselect(self, event): print "unselect called" def start(self): from MDF.sdk.netif import * from MDF.sdk.event import * cmdr = Commander(accept=self.accept, reject=self.reject, configuration=self.configuration, end=self.end, unselect=self.unselect) print "===> INSTANTIATED" cmdr.connect("172.18.91.131") print "===> CONNECTED" cmdr.remoteNegotiation() print "===> RTPNEGOTIATE" if __name__ == "__main__": driver = MDFDrv() driver.start()
I just attended a session at SD2008 on parallelism put on by an Intel engineer this week.The topic was on increasing executable performance by utilizing threading and Intel's Threading Building Blocks (TBB) library. TBB offers some Template style constructs to easily utilize the CPU's multiple cores. Unfortunately, Intel's focus is on C++ and Fortran (statically typed languages). Pondering over execution speed, I was just thinking that Python programs could sure use a bump. Does anyone know whether Python 2.5 or IronPython makes use of the parallel nature of the newer multi-core processors when threading is used? What about utilizing the multi-core even on single threaded programs?
After jotting this down, I did a search to see if anyone else has posed the same question. These are what I found:
I had done some embedding of the Python interpreter into a C++ executable before and had to learn about the GIL. Apparently Python simulates multithreading by allowing each of its threads to obtain the Global Interpreter Lock. Each thread grabs the lock and runs its allotted time while blocking all other threads. From the OS point-of-view, this is still a single thread being time-shared. Adding CPUs won't help performance because only 1 will be utilized while all others are idle.
Anyone have further thoughts or links to share on this topic?
Choosing a Python IDE
Embedding the Python Interpreter into C++
Namedpipes and Python
This is the Python module that allows you to easily hook into existing C code that are exposed as Windows DLLs . As you know, a large portion of existing software today are based on C so this is a major tool in any programmer's toolbox. Starting with Python 2.5, ctypes is a part of the built-in set of batteries which is distributed. This only adds to the usefulness factor.
On Functional Program with Python
Useful things to keep around
Just Useful Tools
One of the greatest benefits of the programming language called Python is that it has a large base of users. Unfortunately, it is also one of its greatest set-backs. Because of the open nature of Python, there are quite a few distributions of the interpreter. The following are some that I know of:
In addition to this, there are different versions of the interpreter floating around: 2.2, 2.3, 2.4, and most recently 2.5. I won't even get started with IronPython.
Compounded upon this wild permutation is the many differing versions of the libraries which we base our code on. Depending on whether the library was included in the core distribution or downloaded and installed on our machine at some point in time, we may have a mix of libraries which differ from anyone else's installation.
Well guess what....: when a Python program executes, the nature of its behavior is very heavily dependent upon whatever permutation of the above is installed on your machine. I was debugging a strange problem that occurred when using the logging module. In the interpreter shell, it operates as expected. From Komodo, it crashes and exhibits very strange behavior. Searching the internet for answers did not help either because logging had been changing quite a bit. On top of this, the answers I found were completely wrong because it assumed a specific version of logging. Of course, all of this is from hindsight so everything seems obvious when it is all laid out.
Ultimately, it turned out that Komodo had packaged their own version of logging (which of course differs from the one my shell uses). Once you know the problem, the answer is pretty easy. However, it does tell me that (in order to obtain consistent program behavior) you practically have to be on top of configuration management for your Python environment. The behavior of your source code is heavily dependent upon the Context of your execution environment.
POST NOTE (9/21/06): the execution context behavior under PythonWin is not exactly the same as in Python. I was using PythonWin along with ctypes. The entire PythonWin executes in the same process context as the script it runs. This means both your editor/debugger and your program run in the same process. (wild!!!) If you execute python.exe from the shell, your script gets spawned as an entirely different process. This is generally how other debuggers work. Depending on what system resources are affected, the script may behave differently whether or not you use PythonWin.