Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Upgrading from IronPython2

Lamparter edited this pageNov 17, 2024 ·2 revisions

IronPython 3.4 uses Python 3.4 syntax and standard libraries and so your Python code will need to be updated accordingly. There are numerous tools and guides available on the web to help porting from Python 2 to 3.

Binary compatibility

The IronPython 3 binaries are not compatible with the IronPython 2 binaries. Modules compiled withclr.CompileModules using IronPython 2 are not compatible and will need to be recompiled using IronPython 3.

Checking for IronPython

In an effort to improve compatibility,sys.platform no longer returnscli. If you wish to check if you're running on IronPython the recommended pattern is to check thatsys.implementation.name is equal toironpython:

ifsys.implementation.name=="ironpython":print("IronPython!")

None is a keyword

None is a keyword in Python 3 and trying to access a member calledNone will raise aSyntaxError. Since this name is frequently used in .NET code (e.g. in enums), code trying to use it is going to throw. You can use alternate syntax in order to access the .NET member, for examplegetattr(x, "None") or an accessor for enumsMyEnum["None"].

# IronPython 2System.StringSplitOptions.None
# IronPython 3System.StringSplitOptions["None"]

Similarly,True andFalse are also keywords in Python 3.

Redirecting output

With IronPython 2, standard output was written to the runtime'sSharedIO.OutputWriter (which wasConsole.Out by default). This is no longer the case with IronPython 3 where the standard output is a binary stream. The output is now written to runtime'sSharedIO.OutputStream. Similarly, standard input and error are now usingSharedIO.InputStream andSharedIO.ErrorStream respectively.

Because of this, using aTextWriter to capture output will no longer work. As a workaround, in order to use aTextWriter as the main method of redirection, one could wrap the writer inside a stream (for example, seeTextStream).

// IronPython 2varengine=Python.CreateEngine();vartextWriter=newMyTextWriter();// no longer works in IronPython 3!engine.Runtime.IO.RedirectToConsole();Console.SetOut(textWriter);
// IronPython 3varengine=Python.CreateEngine();vartextWriter=newMyTextWriter();engine.Runtime.IO.SetOutput(newTextStream(textWriter),textWriter);

Another way of achieving the redirection behavior similar to IronPython 2 is to set engine optionConsoleSupportLevel toSupportLevel.Basic. IronPython 3 still uses binary streams for standard input and output butall three standard streams are set to useTextStream, forwarding to the corresponding writers/reader.

// IronPython 3varengine=Python.CreateEngine(newDictionary<string,object>{{"ConsoleSupportLevel",Microsoft.Scripting.Runtime.SharedIO.SupportLevel.Basic},});vartextWriter=newMyTextWriter();// works again!engine.Runtime.IO.RedirectToConsole();Console.SetOut(textWriter);

This method is particularly useful when embedding the IronPython 3 engine in a host that sets console's writers/reader before the engine is created and the host's code is not accessible to the user (for instance, scripting inLINQPad).

// IronPython 3 in LINQPadvarengine=Python.CreateEngine(newDictionary<string,object>{{"ConsoleSupportLevel",Microsoft.Scripting.Runtime.SharedIO.SupportLevel.Basic},});engine.Execute("print('abc')");// shows output in the "Results" panedynamicans=engine.Execute("input()");// pauses the script and asks for input at the bottom of the "Results" pane; terminate your input with Ctrl+Z, Enter

int Type

One of the major backward incompatible changes in Python 3 isPEP 237 – Unifying Long Integers and Integers: Essentially,long renamed toint. That is, there is only one built-in integral type, namedint; but it behaves mostly like the oldlong type. From the pure Python perspective this means thatint should be used wherever previouslylong was used. More consideration has to be applied in interop cases with .NET.

The Pythonint type in IronPython 3 is implemented asSystem.Numerics.BigInteger (and not asSystem.Int32 as it was in IronPython 2). It can contain in theory an arbitrarily large integer (only limited by the 2 GByte memory boundary).

>>>import clr>>> clr.AddReference("System.Numerics")>>>import System>>>intis System.Numerics.BigIntegerTrue>>>intis System.Int32False>>> clr.GetClrType(int).Name'BigInteger'

This means that in interop cases, when theint type is used (think generics), it will meanBigInteger and notInt32 (which was the case in IronPython 2). To retain IronPython 2 semantics, replaceint withSystem.Int32.

Example:

# IronPython 2System.Collections.Generic.List[int]
# IronPython 3System.Collections.Generic.List[System.Int32]

Overview ofint type equivalency:

IronPython 2IronPython 3.NET
longintSystem.Numerics.BigInteger
intN/ASystem.Int32

Instances ofint

As for instances ofint, mostly for performance reasons, IronPython may use instances ofSystem.Int32 to hold smaller integers, whileBigInteger instances are used for large integers. This is done transparently from the Python side, but again the distinction may become relevant for interop cases. Examples:

i=1# instance of Int32j=1<<31# instance of BigIntegerk=j-1# still BigInteger, as one of the arguments makes the result type BigInteger

This means that the type ofInt32 objects is always reported asint (which is the same asBigInteger). If it is important to check what is the actual type of a given integer object, test if the object is an instance ofSystem.Int32. (An alternative way is a test for the presence ofMaxValue orMinValue. For those properties to be visible,System has to be imported first.)

>>>import System>>>type(i)<class 'int'>>>>isinstance(i, System.Int32)True>>>type(j)<class 'int'>>>>isinstance(j, System.Int32)False>>>hex(i.MaxValue)'0x7fffffff'

The creation of eitherInt32 orBigInteger instances happens automatically by theint constructor. If for interop purposes it is important to create aBigInteger (despite the value fitting in 32 bits), use methodToBigInteger. It convertsInt32 values toBigInteger and leavesBigInteger values unaffected.

>>> bi= i.ToBigInteger()>>>isinstance(j, System.Int32)False

In the opposite direction, if it is essential to createInt32 objects, either use constructors forint orInt32. In the current implementation, the former converts an integer toInt32 if the value fits in 32 bits, otherwise it leaves it asBigInteger. The latter throws an exception if the conversion is not possible. Although the behavior of the constructorint may or may not change in the future, it is always guaranteed to convert the value to the "canonical form" adopted for that version of IronPython.

>>># k is a BigInteger that fits in 32 bits>>>isinstance(k, System.Int32)False>>>hex(k)'0x7fffffff'>>> ki=int(k)# converts k to Int32>>>isinstance(ki, System.Int32)True>>> ki= System.Int32(k)# also converts k to Int32>>>isinstance(ki, System.Int32)True>>># j is a BigInteger that does not fit in 32 bits>>>isinstance(j, System.Int32)False>>>hex(j)'0x80000000'>>> j=int(j)# no type change, j stays BigInteger>>>isinstance(j, System.Int32)False>>> j= System.Int32(j)# conversion failsTraceback (most recent call last):  File "<stdin>", line 1, in <module>OverflowError: Arithmetic operation resulted in an overflow.

Such explicit conversions are in most cases unnecessary since the runtime recognizesint/Int32 equivalence of instances and performs necessary conversions automatically.

>>>import System>>> int_list= System.Collections.Generic.List[int]()>>> int_list.Add(1)# Int32 instance converted to BigInteger>>> int32_list= System.Collections.Generic.List[System.Int32]()>>> int32_list.Add((1).ToBigInteger())# BigInteger instance converted to Int32>>> int_list[0]== int32_list[0]True

Pickling and unpickling ofint

When anint object is serialized usingpickle.dump(x, myfile) and subsequently unpickled withx = pickle.load(myfile) (orpickle.loads(pickle.dumps(x)), this has the same effect as reconstructing the object using theint constructor, i.e.x = int(x). In other words, if thex instance wasBigInteger but the value fits inInt32, it will be reconstructed asInt32.

BigIntegerV2 API

In IronPython 2,long type carries an obsoleteBigIntegerV2 API, accessible after importingSystem. In IronPython 3 this API is not available directly onint instances (regardless of whether the instance isInt32 orBigInteger), but is still accessible in some form throughMicrosoft.Scripting.Utils.MathUtils inMicrosoft.Dynamic.dll.

>>># IronPython 2>>> i=1# instance of Int32 (int)>>> j=1<<64# instance of BigInteger (long)>>>import System>>> j.GetWords()Array[UInt32]((0, 0, 1))>>> i.GetWords()Traceback (most recent call last):  File "<stdin>", line 1, in <module>AttributeError: 'int' object has no attribute 'GetWords'>>>long.GetWords(i)Array[UInt32]((1))
>>># IronPython 3>>> i=1# instance of Int32 (int)>>> j=1<<64# instance of BigInteger (int)>>>import clr>>> clr.AddReference("Microsoft.Dynamic")>>>import Microsoft.Scripting.Utils.MathUtils>>> clr.ImportExtensions(Microsoft.Scripting.Utils.MathUtils)>>> j.GetWords()Array[UInt32]((0, 0, 1))>>> i.GetWords()Traceback (most recent call last):  File "<stdin>", line 1, in <module>AttributeError: 'int' object has no attribute 'GetWords'>>> Microsoft.Scripting.Utils.MathUtils.GetWords(i)Array[UInt32]((1))

Another set of Python-hidden methods onlong in IronPython 2 that are not available onint in IronPython 3 are conversion methods with names likeToXxx. The recommended way to perform type conversions like those is to use type constructors. The exception is the conversion toBigInteger itself, for the reasons explained above.

# IronPython 2j=long(1)i64=j.ToInt64()
# IronPython 3importSystemj= (1).ToBigInteger()i64=System.Int64(j)

range

IronPython'srange is a generator that produces a sequence ofint values. The values are instances ofInt32 orBigInteger, depending on the actual integer value they represent. Whenrange is used in a LINQ context, it exposes interfaceIEnumerable<Int32> and all values generated are of typeInt32. This limits the possible value to the rangeInt32.MinValue toInt32.MaxValue.

🙂 Looks like you've reached the end.

Still looking for more? Browse theDiscussions tab, where you can ask questions to the IronPython community.


🐍IronPython

Clone this wiki locally

[8]ページ先頭

©2009-2025 Movatter.jp