September 11, 2008

Python vs. Java - HTTP GET Request Complexity

Wow.. talk about programming with a ball and chain on! Some languages just take so much code to do a simple thing.

The following 2 programs each do an HTTP GET and print the contents of the URL.

In Java:

import java.net.*;
import java.io.*;

public class JGet {
    public static void main (String[] args) throws IOException {
        try {
            URL url = new URL("http://www.google.com");
    
            BufferedReader in = 
                new BufferedReader(new InputStreamReader(url.openStream()));
            String str;

            while ((str = in.readLine()) != null) {
                System.out.println(str);
            }

            in.close();
        } 
        catch (MalformedURLException e) {} 
        catch (IOException e) {}
    }
}

Equivalent in Python:

import urllib
print urllib.urlopen('http://www.google.com').read()

21 comments:

Robby O'Connor said...

and now here's the groovy version:

new URL("http://google.com").text

=)

--rob

Anonymous said...

print __import__('urllib').urlopen('http://www.google.com').read()

Steve said...

I've said it before and I'll say it again: Java is Object-Oriented COBOL.

Anonymous said...

Python does have some nice built-ins. It's a shame there's no copy stream-to-stream method in the JDK. Most projects will have commons-io or similar available though, leaving it:

IOUtils.copy(new URL("http://www.google.com").openStream(), System.out);

...ignoring error handling etc.

Anonymous said...

This is an issue with the Java "standard library" and not Java the language.

I'm a python fan, but this is an apples to oranges comparison. Compare urllib2 to httpclient (jakarta-commons)

afsina said...

write a simple helper dude. script guys will never learn. just one example:
http://code.google.com/p/jmate/wiki/IoOperations
or end of this one
http://code.google.com/p/jmate/wiki/SimpleFileWriter

Anonymous said...

Where is the exception handling in the Python version?

Alec Munro said...

While it's not entirely apples to apples, it's pretty close, as it relies on the standard library shipped with both languages.
The lack of exception handling in the Python is notable, but not terribly relevant, as it's not the exception handling that makes the Java complex.

As far as writing a tool, or relying a on third-party library, this is of course the thing to do in practicality (unless you are only doing this once, in which case the hassle probably isn't worth it). However, when someone else looking at your code has a problem with that tool or library, they will have to look it up. For Python, it's always:

http://docs.python.org/lib/lib.html

While this doesn't mean Python is the tool for every job, it tends to give you pretty clean results, and in most cases, avoids the following questions:
- Do I need to use a third-party library for this?
-- If so, which one should I use?
-- Is it approved for use in my company?
- Should I build a wrapper for this code, to make it simpler to read?
-- If so, what are the interfaces to the wrapper?

... and eventually ...

- Where's the documentation for this?

That's not to say these questions don't come up in Python, but the "batteries-included" approach means they come up far less often.

flow said...

@"""This is an issue with the Java "standard library" and not Java the language."""

not quite, i believe; having to say `gimme Foobar x = new Foobar(...)` all the time drives me nuts, and this is the language, not the library. plus of course all the braces. take these two things away from the java example, and, yes, it does look a lot more like python. (a library is not going to give you that, though, which may account for the popularity of scripting languages running atop the java VM).

@"""Where is the exception handling in the Python version?"""

so where is it in the java version, in the first place? nowhere! still the code is studded with no less than four exception-related statements: the `throws` declaration, the `try` clause, and two `catch` clauses. what do these lines add to the functioning of the code? zilch!! yet java will refuse to run it (i believe) when absent. this misfeature has been criticized before: The Trouble with Checked Exceptions.

even when you say: well, at least those exceptions got properly documented in the code—these useless stubs still cause a deeper problem on the client side: when the implementation of the called code changes to include other exceptions, then all of the client code must adapt to that change, even if the client code happens to call a library in ways that could in fact never cause the newly introduced exceptions to be raised!

that's hilarious, no? a language that forces me to say `int i = 5`, write `catch` clauses that serve no purpose, and, on top of that, forces me to partially document third-party libraries? say what?

Janus Troelsen said...

Even shorter in PHP :P (hehehe):
echo file_get_contents("http://www.google.com/");

Anonymous said...

String fileContent = FileUtils.readString("c:/autoexec.bat");

String urlContent = HttpUtils.readString("http://www.why_are_all_python_fans_clueless_bozos.htm");

flow said...

@"""String urlContent = HttpUtils.readString("http://www.why_are_all_python_fans_clueless_bozos.htm")"""

print """why do all the java bozos believe in that `String x=getString()` mojo when it does not serve any useful purpose?"""

seriously: as much as sth like `def f( int x )` is (among other things) missing from python—how does it feel to write in a language that seriously distinguishes between `"x"` and `new String("x")` and so on? where some numbers are objects and others are not?

some desktop java applications really really impress me, and the community sure can claim more than one achievement, but the yuckie basics of the language and various other hallmarks leading to ‘for-want-of-a-nail’-isms (for which see Steve Yegge’s now-classical piece of codepoetry) have always put me off (save for one experience i do not care to repeat).

Erik said...

Wow! Yet another my language is bigger/shorter/smarter than yours...

In case you don't know: Lisp already did it far better over 20 years ago, and I'm not even taalking about Smalltalk ;-)

Erik

Anonymous said...

wget -O lol google.com && cat lol & rm lol

Janus Troelsen said...

Why output to file?

wget -q -O - 'http://www.google.com/'

and with curl:

curl -s 'http://www.google.com/'

Anonymous said...

Being really fair with Java requires adding Exception Handling to the Python code.

Of course the overall conclusion will not change: Java sucks when compared to Python, either from the language point of view or when it comes to the standard library...

flow said...

@"""Being really fair with Java requires adding Exception Handling to the Python code."""

as indicated above, no addition python code is needed; it is already largely equivalent with the java code as far as exception handling goes. the java code does NOT do ANY kind of useful exception handling. the java snippet contains the bare minimum necessary to make this kind of operation compile at all. the `throw` clause announces the possibility of an uncaught exception, and the two catch clauses, if memory serves me, simply make it so that `MalformedURLException` and `IOException` will be swallowed silently---i think java mandates that you deal with these exceptions right where you use the called method, and the implementations given are bare minimum do-nothings (this may be wrong in details, pls correct me). see e.g. http://en.wikipedia.org/wiki/Exception_handling#Checked_exceptions for more.

Matej Knopp said...

Good luck when you'll have to refactor the python code.

Timo said...

Does the python version convert linefeeds to native linefeeds?

Anonymous said...

It can be made a little shorter, but it really is a mess. Yet no script language can be made as fast as the vm with jit compiling.

import java.net.*;
import java.io.*;

public class JGet {
public static void main (String[] args) throws Exception {
BufferedReader in =
new BufferedReader(
new InputStreamReader(
new URL("http://www.google.com").openStream()));
while(in.ready()){
System.out.println(in.readLine());
}
in.close();
}
}


This doesn't support alternative character sets, so it's better to use commons.httpclient

import org.apache.commons.httpclient.*;
import org.apache.commons.httpclient.methods.*;

public class HttpGet {

public static void main(String[] args) throws Exception {

GetMethod method = new GetMethod("http://www.apache.org/");
new HttpClient().executeMethod(method);
System.out.println(new String(method.getResponseBody(), method.getResponseCharSet()));

}
}

Caleb James DeLisle

thanos said...

How about doing a simple file copy ?
Here is the python version:
open('dst_file_name','wb').write(open('src_file_name','rb').read())

Here is the Java version:

// Sorry too Lazy so I'm going to use JPython ;)

import org.python.core.io.FileIO
.
.
.
FileIO src = new FileIO('src_file_name','rb');
FileIO dst = new FileIO('dst_file_name','wb');
dst.write(src.read());
src.close();
dst.close();