Differences between IronPython 1.0.x and CPython 2.4.3

Information in this document is subject to change without notice. The example companies, organizations, products, people, and events depicted herein are fictitious. No association with any real company, organization, product, person or event is intended or should be inferred. Complying with all applicable copyright laws is the responsibility of the user. Without limiting the rights under copyright, no part of this document may be reproduced, stored in or introduced into a retrieval system, or transmitted in any form or by any means (electronic, mechanical, photocopying, recording, or otherwise), or for any purpose, without the express written permission of Microsoft Corporation.

Microsoft may have patents, patent applications, trademarked, copyrights, or other intellectual property rights covering subject matter in this document. Except as expressly provided in any written license agreement from Microsoft, the furnishing of this document does not give you any license to these patents, trademarks, copyrights, or other intellectual property.

© Microsoft Corporation. All rights reserved.

Microsoft, MS-DOS, MS, Windows, Windows NT, MSDN, Active Directory, BizTalk, SQL Server, SharePoint, Outlook, PowerPoint, FrontPage, Visual Basic, Visual C++, Visual J++, Visual InterDev, Visual SourceSafe, Visual C#, Visual J#, and Visual Studio are either registered trademarks or trademarks of Microsoft Corporation in the U.S.A. and/or other countries.

Other product and company names herein may be the trademarks of their respective owners.

  1. Overview.........................................................................................................................................
  2. Standard Types, Functions, and Behaviors...........................................................................
  3. Regular Expressions....................................................................................................................
  4. Extension Modules.......................................................................................................................
  5. Interpreter and Environment.....................................................................................................
  6. Garbage Collection.......................................................................................................................

Overview

CPython (the standard for Python) and IronPython are two different implementations of the Python language. While a Language Referenceexists for the Python language, there are a number of features of the language that are incompletely specified. The following lists all known differences between the two implementations of the Python language. These differences range from the trivial (such as, IronPython has different error messages in some cases, but raises the same exception type) to the significant (such as, IronPython does not implement some standard extension modules like cmath).

Any other differences not listed here are purely accidental omissions. Please submit a bug report at http://www.codeplex.com/ironpythonso that we can either fix the difference or update this document until we can fix it.

The IronPython team is very concerned about compatibility with CPython, and we plan to fix all incompatibilities that are not acceptable. Some incompatibilities (for example, those due to garbage collection implementation) are officially acceptable. We determined this by discussing these issues with the Python community. In some other cases, the CPython test suite needs to be updated where it makes inappropriate assumptions about implementation characteristics.

This list has been updated to describe the differences between IronPython 1.0 and CPython 2.4.3.

Standard Types, Functions, and Behaviors

IronPython sometimes displays different error messages for SyntaxError exceptions. The raised exception type (SyntaxError) is the same as in CPython.

IronPython has slightly different error messages when parsing arguments to eval(). IronPython identifies the file name as "<string>", but CPython does not report anything as a file name or that the error was found while parsing a string.

IronPython allows slots to be defined on subclasses of tuple (for example, "class foo(tuple): slots = ‘abc’”). CPython does not allow this and instead raises a TypeError stating non-empty slots are not supported on subtypes of tuple.

IronPython cannot call reduce or reduceex on None. IronPython mistakenly believes it does not have an instance and therefore disallows calls of reduce and reduceex on None. For reduce both implementations raise a TypeError but for different reasons. For reduceex IronPython throws an exception, but CPython can successfully reduce the None object.

When dir is used on instances of a type that has a metaclass, the resulting list has some missing attributes. By default CPython defines delattr, getattribute, hash, setattr, and str. IronPython does not display these in dir()’s results but they are callable.

Tracebacks display carets indicating the column for syntax errors where there are invalid assignments (for example, “def f(x): [x for x in x] = x”). CPython does not do this. Reproducing this behavior requires that you use the CPython standard library for displaying tracebacks.

When getting a method from a class that has not been instantiated, IronPython returns an unbound method while CPython returns a function.
    class C(object):
        def foo(self): pass

    print C.__getattribute__(C, 'foo')



IronPython allows calling setattr on types. CPython disallows this and raises a type error, stating that you can’t apply setattr to a type object:
    class foo(object): pass
    foo.__setattr__(foo, ‘__str__’, ‘bar’)



IronPython modules have a dict attribute that contains the dictionary for the module. In IronPython “dir(dict)” displays the usual attributes for a dictionary, but CPython raises a NameError because dict is not defined.

IronPython catches string exceptions by value, but CPython catches string exceptions by reference. For example, IronPython will catch this exception, but CPython won’t:
    try: raise 'abc'
    except 'a' + 'bc': pass



When accessing a file with universal new line support, IronPython and CPython can return different sizes for the file after reading partial strings.

IronPython and CPython display different error messages when calling a user type that does not take any parameters, but they do raise the same exception type.

The sys.version value is different between the two implementations.

The maximum recursion limit in IronPython is unlimited by default, and you can call sys.setrecursionlimit() to set it to the maximum stack height.

IronPython is more lenient regarding the use of keyword arguments in many circumstances. For example, “[].append.call(item=’abc’)” works in IronPython but raises an exception in CPython. Regarding _weakref, IronPython allows using keyword arguments on the weakproxy method wrappers. IronPython is also less restrictive for some string methods. For example, the following works in IronPython but raises an error in CPython:
    x = ""
    x.center(1, fillchar='*')



IronPython has a different type hierarchy than CPython for representing system types. IronPython uses a single base class with distinct subtypes for built-in and user types. If programmers try to test whether an object is a type object by using Python's identity operator (is), instead of using instanceof(), then they may get different results.

IronPython allows setting attributes on built-in functions.

IronPython does not allow you to set attributes on builtins, but CPython does let you do this.

IronPython allows you to set the value of builtins, as does CPython, but the results are different. For example, import will no longer work in IronPython, but the built-in function min() will continue to work.

IronPython reports the value of builtins to be a type, but CPython reports it to be a module.

IronPython does not include local variables in covarnames. For example, "foo.funccode.co-varnames" for "def foo (x, y): z = 10" only returns 'x' and 'y'.

IronPython raises a ValueError for very large exponents (for example, 10 ** 735293857239475) while CPython hangs trying to compute the number. We probably won't fix this one.

IronPython's compile() function behaves differently than CPython's compile() function in some cases. CPython's compile function raises a SyntaxError for some trailing whitespace, but it does not do this when compiling a file. For example, the "x = compile('def f(a):\n\treturn a\n\t', '', 'single')" trailing \t causes an error in this case. We do not intend to fix this difference.

IronPython uses unicode characters and strings, not ASCII as CPython does. For example "'%c' % i" for 255 < i <65536 raises an error in CPython but succeeds in IronPython. We may wait to see how Python3k incorporates unicode before fixing this issue.

IronPython will compile files whose identifiers use non-ASCII characters if the file has an encoding comment such as "# -*- coding: utf-8 -*-". CPython will not compile such a file in any case.

IronPython does not support a DeprecationWarning mechanism.

IronPython does not support a -W switch to control warnings.

IronPython has slightly different system-defined attribute names on some types. For example, try "dir(True)" in both CPython and IronPython.

Setting sys.std* attributes does not affect IronPython’s console behavior.

If executing within the dynamic context of a generator, and an exception is raised, IronPython exhibits a different behavior than CPython. IronPython will continually re-raise the same exception every time you call next() on the generator. CPython raises a StopIteration exception on subsequent calls to next().

IronPython does not handle falling off the end of generator functions the same way as CPython. When you call next() after a last yield statement has executed, IronPython continually returns execution to the point immediately after that yield statement, executes to the end of the function, and then raises a StopIteration exception. CPython executes from the last yield to the end of the function only one time, and then subsequent calls to next() immediately raise a StopIteration exception.

IronPython does not allow yield statements in nested try blocks.

IronPython raises an exception when it cannot convert a string to a unicode string, and CPython just returns the argument to unicode().

IronPython's codecs module implementation is incomplete. There are several replaceerror/lookup_error handlers that IronPython does not implement.

IronPython does not implement type.mro, and user overrides do not affect how a type's mro works. In CPython you can override a type’s mro method to alter the method resolution order, but IronPython raises an exception if you try to set type.mro. Calling mro on any type raises an exception, but mro still works on types.

IronPython does not support overriding getattribute for some user-defined subclasses of built-in types.

When printing expression results in the console, IronPython calls str on new style classes while CPython calls repr.

IronPython gives different error messages and raises different exceptions in some situations using the complex built-in function. For example, calling complex on an old style class instance in CPython raises an AttributeError due to no float function existing, but IronPython raises a TypeError. Doing the same thing on a new style class raises a TypeError in both implementations, but CPython's message explains the argument must be a string or number while IronPython's message just says it cannot convert to complex.

IronPython raises different exceptions than CPython (and sometimes raises exceptions when CPython does not) in isinstance() with complex class definitions that affect bases and return bases in various ways. See http://www.codeplex.com/WorkItem/View.aspx?ProjectName=IronPython&WorkItemId=2169 for details.

IronPython’s behavior differs from CPython’s behavior if you call del on builtin.pow and then try to print the value of pow within a module. Importing or executing the module from the command line in IronPython will print "<built-in function pow>" while CPython raises a NameError.

IronPython has extra attributes ('msg' and 'clsException') on exception objects.

IronPython does not return a code object if it encounters a syntax warning when calling compile(). IronPython raises a SyntaxWarning exception, but CPython catches and prints the exeption before returning a code object.

IronPython does not invoke the setattr_ attributes for old style classes when setting an attribute. See http://www.codeplex.com/WorkItem/View.aspx?ProjectName=IronPython&WorkItemId=2295 for more info.

IronPython supports fromkeys() on some dictionaries for which CPython does not provide fromkeys() support. For example, “file.dict.fromkeys” returns a method in IronPython and raises a TypeError in CPython.

IronPython allows you to set a key of value 2 in class’s dict, but CPython does not. CPython only allows you to do this with the dict of a class instance, not the class itself. Try “C.__dict__[2] = ‘2’”.

IronPython supports slots for subtypes of type, but CPython does not. For example, the following works in IronPython:
    class foo(type): 
        __slots__ = [“abc”]



IronPython doesn’t support supplying named values for format string directives if the name has parentheses in it, for example, “%((foo))s” % {‘(foo)’ : ‘fooval’ }.

When formatting float numbers, IronPython doesn’t raise an Overflow exception for formatting with too high a precision (for example, >=67).

IronPython doesn’t support overriding getattribute on built-in objects.

IronPython cannot create weakref proxies that reference deque and set objects.

IronPython supports ‘continue’ statements in ‘finally’ clauses.

IronPython’s built-in function reversed() behaves slightly differently than CPython’s reversed() function. For example, calling len() on the result of “reversed(xrange(5))” raises a TypeError. Also, calling len() on the result of calling reversed() on custom iterators (for example, a class that supports getitem and len) fails. This behavior happens because the reversed() iterator doesn’t provide access to the original len implementation.

IronPython’s implementation of buffer doesn’t support binary operations between buffers and strings (for example, concatenation with a buffer and string).

IronPython does not call len on old style classes when slicing. This results in the end index potentially being negative in IronPython. CPython adjusts to the appropriate end index, but it raises an AttributeError if the old style class does not have a len attribute.

IronPython does not allow opening partitions and drives for read as binary files, but CPython does allow this. For example, IronPython detects the “\\.\” idiom in “f = file(r'\\.\PhysicalDrive', 'rb')” and raises a ValueError since .NET does not support this functionality.

IronPython’s built-in apply function has a bug in that it requires at least two arguments.

Printing numbers on a machine with French locales produces different output:

IronPython CPython
>>> x = 1.234 >>> x = 1.234
>>> x >>> x
1.234 1.234
>>> print x print x
1,234 1.234



Small integer caching in IronPython is different than in standard CPython. If you set i = 2 and then test "i is 2", the code produces different results in IronPython and CPython. However, the consistency of the result of such expressions is not guaranteed even within CPython, which seems to be using different small integer caching strategies for different situations:

IronPython CPython
>>> i=5 >>> i=5
>>> i is 5 >>> i is 5
False True
>>> i=5000 >>> i=5000
>>> i is 5000 >>> i is 5000
False False


Regular Expressions

IronPython returns a regular expression match when your pattern matches the beginning of a string, but you supplied a start index past the start of the string. In this same case CPython returns None.

IronPython raises a more specific exception (IndexError instead of sre_constants.error) when using an invalid group reference in regular expressions with named groups -- for example, “re.sub(r'(?P<id>b)', '\g<1>\g<30>blah', 'bb')”.

Since the IronPython regular expression implementation uses the .NET Framework regular expressions implementation, IronPython supports some syntax not supported by CPython (note, CPython has a similar syntax for affecting the entire pattern, but it is different than these mechanisms in syntax and scope of effect):
  • (?i:foo) -- ignore case
  • (?m:foo) -- multi-line mode (^ and $ match at the beginning and end, respectively, of any line, not just beginning and end of the whole string)
  • (?s:foo) -- single line mode (period “.” matches every character instead of every character except \n)
  • (?x:foo bar) -- ignore whitespace in the pattern

Extension Modules

IronPython support importing .NET Frameworks assemblies as extension modules. Usually you need to import the built-in extension module clr and then call one of the clr.AddReference... functions.

Some CPython built-in extension modules do not exist in IronPython:
  • _bisect
  • codecshk
  • audioop
  • _multibytecodec
  • parser
  • array
  • msvcrt
  • codecskr
  • sha
  • strop
  • _heapq
  • codecsjp
  • imageop
  • mmap
  • _subprocess
  • codecstw
  • regex
  • zipimport
  • cmath
  • _winreg
  • xxsubtype
  • codecscn
  • md5
  • codecsiso2022
  • rgbimg
  • _csv
  • signal (.NET does not support signals)
  • _hotshot
  • _symtable

The sys module does exist though it is not listed in sys.builtinmodulenames.

IronPython has these additional modules: 're', 'copy_reg', 'socket'. These are built in rather than being implemented in Python either to leverage the .NET Frameworks or to avoid dependencies on CPython for a minimal installation.

Passing malformed data to binascii.a2bbase64 results in different error messages. IronPython will raise a TypeError in this situation, and CPython will raise a binascii.Error. For example try executing “binascii.a2bbase64(‘A’)”.

IronPython’s pickle module doesn’t support fast mode.

The pickle implementation in IronPython doesn’t doesn’t handle all cases of pickling deque objects (recursive deque for example) and sets.

The doctest module does not run in IronPython.

IronPython doesn’t support the select module.

IronPython doesn’t support the _testcapi module.

IronPython doesn’t implement socket.getservbyname() because IronPython uses .NET base class libraries to implement the socket module, and they don’t provide the support for that function.

IronPython doesn’t support the makefile method on socket objects.

IronPython does not have an xxsubtypes built-in module.

IronPython has no os.system function.

Interpreter and Environment

IronPython does not by default have the standard CPython libs on its path (for example, . You can fix this by adding these two lines to the site.py file in the IronPython lib directory:
    import sys
    
    sys.path.append(r"c:\python24\lib")



IronPython does not redirect the interpreter's error output in response to setting sys.stderr.

IronPython has different command line editing support than CPython.

IronPython supports different command line options than CPython supports. Invoke ipy.exe with the "-?" switch to see options.

IronPython's sys.builtinmodulenames tuple contains different values than CPython's result. See section Extension Modules for differences.

IronPython has several incompatibilities relating to the interpreter and the sys module’s hooks:
  • settrace - Calling this raises a NotImplementedException.
  • apiversion - This always has the value: "IronPython does not support the C APIs, the apiversion is not supported".
  • displayhook - Setting this will throw a NotImplementedException.
  • _getframe - Calling this function raises a ValueError exception.
  • excepthook - IronPython does not support excepthook because it does not implement sys.excepthook(). IronPython does not currently support replacing function definitions in the sys module. Note, excepthook is an attribute in the sys module, but it is bound to a string: "IronPython does not support sys.excepthook".
  • setcheckinterval - IronPython does not use the value set with this function.

IronPython allows access to dict, module, class, and init at the global level, but CPython does not.

Python prohibits using identifiers before the occurrence of global statement if the global statement includes the identifier. In these cases, CPython reports a syntax warning while IronPython raises a SyntaxWarning exception. For example:
    def f():
        a = 1
        global a



The sys.getframe() function is not supported by IronPython. In addition, the semantic of deleting the sys.getframe is different than CPython’s. In IronPython, once sys.getframe is deleted, it is not possible to store a value to sys.getframe.

Garbage Collection

IronPython has a more modern GC whereas CPython uses reference counting, and IronPython's GC choice is considered to be a valid and acceptable implementation. This has several effects which are listed below.

IronPython users don't need to worry about handling circular references as these are guaranteed to be collected properly. This behavior is acceptable.

IronPython does not have guarantees for when finalization or system resource freeing occurs. This can cause problems for people who use open("foo", 'r').read() excessively. This behavior is acceptable.

IronPython does not immediately invoke del methods when del is called on a variable; it happens during the next GC pass. Similarly, using del on an object that a weakref object refers to and then immediately testing if the weakref is None may return False. This behavior is acceptable.

Calling sys.getrefcount raises a NotImplementedError. Alternatively IronPython could always return some positive constant since there's a reference that was passed to getrefcount.

In CPython you can observe the re-use of some tuple objects in some situations, but this is an implementation detail that no one should depend on. In IronPython there is no such re-use.

Last edited Jul 17, 2008 at 4:05 PM by dfugate, version 1

Comments

ekowibowo Nov 26, 2013 at 12:28 AM 
I think we must be able to differentiate between what Python is (which is a Specification), what CPython is (which is commonly accepted by the community as Python, although it actually _is_ an implementation of the Specification) and what IronPython is (which is Microsoft implementation of the afforemention specification).

hajikelist Oct 28, 2010 at 10:33 PM 
Why not just use Python? what's the deal here... is there some reason for not using the *real* Python from .NET? / vice versa ?
It's unfortunate that existing Python code is essentially useless since the implementations are disparate.
Half an apple is better than no apple, however.