diff --git a/doc/src/sgml/plpython.sgml b/doc/src/sgml/plpython.sgml
index aaf758d..da27874 100644
--- a/doc/src/sgml/plpython.sgml
+++ b/doc/src/sgml/plpython.sgml
@@ -308,14 +308,19 @@ $$ LANGUAGE plpythonu;
       </para>
      </listitem>
 
+	 <listitem>
+      <para>
+       PostgreSQL <type>real</type> and <type>double</type> are converted to
+       Python <type>float</type>.
+      </para>
+     </listitem>
+
      <listitem>
       <para>
-       PostgreSQL <type>real</type>, <type>double</type>,
-       and <type>numeric</type> are converted to
-       Python <type>float</type>.  Note that for
-       the <type>numeric</type> this loses information and can lead to
-       incorrect results.  This might be fixed in a future
-       release.
+       PostgreSQL <type>numeric</type> is converted to
+       Python <type>Decimal</type>. This type is imported from 
+	   <literal>cdecimal</literal> package if it is available. If cdecimal
+	   cannot be used, then <literal>decimal.Decimal</literal> will be used.
       </para>
      </listitem>
 
diff --git a/src/pl/plpython/expected/plpython_types.out b/src/pl/plpython/expected/plpython_types.out
index 4641345..30c4455 100644
--- a/src/pl/plpython/expected/plpython_types.out
+++ b/src/pl/plpython/expected/plpython_types.out
@@ -216,31 +216,47 @@ CREATE FUNCTION test_type_conversion_numeric(x numeric) RETURNS numeric AS $$
 plpy.info(x, type(x))
 return x
 $$ LANGUAGE plpythonu;
-/* The current implementation converts numeric to float. */
+/* The current implementation converts numeric to decimal.Decimal. */
 SELECT * FROM test_type_conversion_numeric(100);
-INFO:  (100.0, <type 'float'>)
+INFO:  (Decimal('100'), <class 'decimal.Decimal'>)
 CONTEXT:  PL/Python function "test_type_conversion_numeric"
  test_type_conversion_numeric 
 ------------------------------
-                        100.0
+                          100
 (1 row)
 
 SELECT * FROM test_type_conversion_numeric(-100);
-INFO:  (-100.0, <type 'float'>)
+INFO:  (Decimal('-100'), <class 'decimal.Decimal'>)
 CONTEXT:  PL/Python function "test_type_conversion_numeric"
  test_type_conversion_numeric 
 ------------------------------
-                       -100.0
+                         -100
 (1 row)
 
 SELECT * FROM test_type_conversion_numeric(5000000000.5);
-INFO:  (5000000000.5, <type 'float'>)
+INFO:  (Decimal('5000000000.5'), <class 'decimal.Decimal'>)
 CONTEXT:  PL/Python function "test_type_conversion_numeric"
  test_type_conversion_numeric 
 ------------------------------
                  5000000000.5
 (1 row)
 
+SELECT * FROM test_type_conversion_numeric(1234567890.0987654321);
+INFO:  (Decimal('1234567890.0987654321'), <class 'decimal.Decimal'>)
+CONTEXT:  PL/Python function "test_type_conversion_numeric"
+ test_type_conversion_numeric 
+------------------------------
+        1234567890.0987654321
+(1 row)
+
+SELECT * FROM test_type_conversion_numeric(-1234567890.0987654321);
+INFO:  (Decimal('-1234567890.0987654321'), <class 'decimal.Decimal'>)
+CONTEXT:  PL/Python function "test_type_conversion_numeric"
+ test_type_conversion_numeric 
+------------------------------
+       -1234567890.0987654321
+(1 row)
+
 SELECT * FROM test_type_conversion_numeric(null);
 INFO:  (None, <type 'NoneType'>)
 CONTEXT:  PL/Python function "test_type_conversion_numeric"
diff --git a/src/pl/plpython/expected/plpython_types_3.out b/src/pl/plpython/expected/plpython_types_3.out
index 511ef5a..d50e7eb 100644
--- a/src/pl/plpython/expected/plpython_types_3.out
+++ b/src/pl/plpython/expected/plpython_types_3.out
@@ -216,31 +216,47 @@ CREATE FUNCTION test_type_conversion_numeric(x numeric) RETURNS numeric AS $$
 plpy.info(x, type(x))
 return x
 $$ LANGUAGE plpython3u;
-/* The current implementation converts numeric to float. */
+/* The current implementation converts numeric to decimal.Decimal. */
 SELECT * FROM test_type_conversion_numeric(100);
-INFO:  (100.0, <class 'float'>)
+INFO:  (Decimal('100'), <class 'decimal.Decimal'>)
 CONTEXT:  PL/Python function "test_type_conversion_numeric"
  test_type_conversion_numeric 
 ------------------------------
-                        100.0
+                          100
 (1 row)
 
 SELECT * FROM test_type_conversion_numeric(-100);
-INFO:  (-100.0, <class 'float'>)
+INFO:  (Decimal('-100'), <class 'decimal.Decimal'>)
 CONTEXT:  PL/Python function "test_type_conversion_numeric"
  test_type_conversion_numeric 
 ------------------------------
-                       -100.0
+                         -100
 (1 row)
 
 SELECT * FROM test_type_conversion_numeric(5000000000.5);
-INFO:  (5000000000.5, <class 'float'>)
+INFO:  (Decimal('5000000000.5'), <class 'decimal.Decimal'>)
 CONTEXT:  PL/Python function "test_type_conversion_numeric"
  test_type_conversion_numeric 
 ------------------------------
                  5000000000.5
 (1 row)
 
+SELECT * FROM test_type_conversion_numeric(1234567890.0987654321);
+INFO:  (Decimal('1234567890.0987654321'), <class 'decimal.Decimal'>)
+CONTEXT:  PL/Python function "test_type_conversion_numeric"
+ test_type_conversion_numeric 
+------------------------------
+        1234567890.0987654321
+(1 row)
+
+SELECT * FROM test_type_conversion_numeric(-1234567890.0987654321);
+INFO:  (Decimal('-1234567890.0987654321'), <class 'decimal.Decimal'>)
+CONTEXT:  PL/Python function "test_type_conversion_numeric"
+ test_type_conversion_numeric 
+------------------------------
+       -1234567890.0987654321
+(1 row)
+
 SELECT * FROM test_type_conversion_numeric(null);
 INFO:  (None, <class 'NoneType'>)
 CONTEXT:  PL/Python function "test_type_conversion_numeric"
diff --git a/src/pl/plpython/plpy_main.c b/src/pl/plpython/plpy_main.c
index 0dad843..54a4caf 100644
--- a/src/pl/plpython/plpy_main.c
+++ b/src/pl/plpython/plpy_main.c
@@ -147,7 +147,9 @@ PLy_init_interp(void)
 	if (PLy_interp_safe_globals == NULL)
 		PLy_elog(ERROR, "could not create globals");
 	PyDict_SetItemString(PLy_interp_globals, "GD", PLy_interp_safe_globals);
+	
 	Py_DECREF(mainmod);
+
 	if (PLy_interp_globals == NULL || PyErr_Occurred())
 		PLy_elog(ERROR, "could not initialize globals");
 }
diff --git a/src/pl/plpython/plpy_typeio.c b/src/pl/plpython/plpy_typeio.c
index 6a9a2cb..6e52ae4 100644
--- a/src/pl/plpython/plpy_typeio.c
+++ b/src/pl/plpython/plpy_typeio.c
@@ -18,6 +18,7 @@
 #include "utils/memutils.h"
 #include "utils/syscache.h"
 #include "utils/typcache.h"
+#include "utils/numeric.h"
 
 #include "plpython.h"
 
@@ -26,7 +27,6 @@
 #include "plpy_elog.h"
 #include "plpy_main.h"
 
-
 /* I/O function caching */
 static void PLy_input_datum_func2(PLyDatumToOb *arg, Oid typeOid, HeapTuple typeTup);
 static void PLy_output_datum_func2(PLyObToDatum *arg, HeapTuple typeTup);
@@ -35,7 +35,7 @@ static void PLy_output_datum_func2(PLyObToDatum *arg, HeapTuple typeTup);
 static PyObject *PLyBool_FromBool(PLyDatumToOb *arg, Datum d);
 static PyObject *PLyFloat_FromFloat4(PLyDatumToOb *arg, Datum d);
 static PyObject *PLyFloat_FromFloat8(PLyDatumToOb *arg, Datum d);
-static PyObject *PLyFloat_FromNumeric(PLyDatumToOb *arg, Datum d);
+static PyObject *PLyDecimal_FromNumeric(PLyDatumToOb *arg, Datum d);
 static PyObject *PLyInt_FromInt16(PLyDatumToOb *arg, Datum d);
 static PyObject *PLyInt_FromInt32(PLyDatumToOb *arg, Datum d);
 static PyObject *PLyLong_FromInt64(PLyDatumToOb *arg, Datum d);
@@ -450,7 +450,7 @@ PLy_input_datum_func2(PLyDatumToOb *arg, Oid typeOid, HeapTuple typeTup)
 			arg->func = PLyFloat_FromFloat8;
 			break;
 		case NUMERICOID:
-			arg->func = PLyFloat_FromNumeric;
+			arg->func = PLyDecimal_FromNumeric;
 			break;
 		case INT2OID:
 			arg->func = PLyInt_FromInt16;
@@ -516,16 +516,33 @@ PLyFloat_FromFloat8(PLyDatumToOb *arg, Datum d)
 }
 
 static PyObject *
-PLyFloat_FromNumeric(PLyDatumToOb *arg, Datum d)
+PLyDecimal_FromNumeric(PLyDatumToOb *arg, Datum d)
 {
-	/*
-	 * Numeric is cast to a PyFloat: This results in a loss of precision Would
-	 * it be better to cast to PyString?
-	 */
-	Datum		f = DirectFunctionCall1(numeric_float8, d);
-	double		x = DatumGetFloat8(f);
+	char *x;
+	PyObject *pvalue, *value, *decimal, *decimal_dict;
+	static PyObject *decimal_ctor;
+
+	/* Try to import cdecimal, if it doesnt exist, fallback to decimal */
+	if (decimal_ctor == NULL)
+	{
+		decimal = PyImport_ImportModule("cdecimal");
+		if (decimal == NULL)
+		{
+			PyErr_Clear();
+			decimal = PyImport_ImportModule("decimal");
+		}
+		if (decimal == NULL)
+			PLy_elog(ERROR, "could not import module 'decimal'");
+
+		decimal_dict = PyModule_GetDict(decimal);
+		decimal_ctor = PyDict_GetItemString(decimal_dict, "Decimal");
+		Py_DECREF(decimal_dict);
+	}
 
-	return PyFloat_FromDouble(x);
+	x = DatumGetCString(DirectFunctionCall1(numeric_out, d));
+	pvalue = PyString_FromString(x);
+	value = PyObject_CallFunctionObjArgs(decimal_ctor, pvalue, NULL);
+	return value;
 }
 
 static PyObject *
diff --git a/src/pl/plpython/sql/plpython_types.sql b/src/pl/plpython/sql/plpython_types.sql
index 6a50b42..6bf0c4a 100644
--- a/src/pl/plpython/sql/plpython_types.sql
+++ b/src/pl/plpython/sql/plpython_types.sql
@@ -90,10 +90,12 @@ plpy.info(x, type(x))
 return x
 $$ LANGUAGE plpythonu;
 
-/* The current implementation converts numeric to float. */
+/* The current implementation converts numeric to decimal.Decimal. */
 SELECT * FROM test_type_conversion_numeric(100);
 SELECT * FROM test_type_conversion_numeric(-100);
 SELECT * FROM test_type_conversion_numeric(5000000000.5);
+SELECT * FROM test_type_conversion_numeric(1234567890.0987654321);
+SELECT * FROM test_type_conversion_numeric(-1234567890.0987654321);
 SELECT * FROM test_type_conversion_numeric(null);
 
 
