Importing Static Methods with IPy

Like .NET, Python uses namespaces to avoid name collisions. However, the semantics are a bit different. If you want to use a type or function from a a given namespace in Python, you have to import it into your current scope. For example, if you want to use the Python datetime built-in module, you would import it into the current scope and use it like this:

import datetime
bush_last_day = datetime.date(2009,1,20)

Notice that when I import a Python module this way, it’s scoped into it’s namespace, which forces me to use the entire namespace scoped name to access the type. Of course, that gets tedious quickly, so Python provides a way to import a type from a specific namespace into your current scope like this:

from datetime import date
bush_last_day = date(2009,1,20)

With IronPython, you can do import .NET namespaces as well. Here’s that same code using the standard .NET DateTime class.

from System import DateTime
bush_last_day = DateTime(2009,1,20)

What I didn’t know is that you can import static methods & properties from .NET types into the current scope using the same syntax. Here’s an example:

from System.DateTime import Now

if Now >= bush_last_day:
    print 'celebrate'
else:
    print (bush_last_day - Now).Days, 'days left'

Being able to import a static method into the current scope is pretty convenient. Thanks to my teammate Jimmy for cluing me into this IPy feature.

One caveat though: in Python, you can import an entire namespace into your current scope. You can do that with .NET namespaces, but not with .NET types

from datetime import *         # this works

from System import *           # so does this

from System.DateTime import *  # this doesn’t work

Update: Michael Foord pointed out that if you import Now as I describe above, it places a DateTime object representing the time you imported it into local scope, rather than placing the underlying get_Now static method in local scope. So while DateTime.Now always returns a new value, Now never changes. Sounds like an IPy bug to me, but I’ll have to circle back with the team to be sure.

Comments:

Well... personally I think it is a terrible abuse of the import mechanism. LOL :-)
I was mostly being a troublemaker with that comment, but I know that this feature has confused at least one IronPython user. He did exactly as you did in your example: from System.DateTime import Now and was then surprised that when he used Now it didn't update as it should. This is because in Python you can't use the import machinery to access static members on classes. When you import a class method from IronPython you are doing something not normally possible from Python - so what is actually happening may not be immediately obvious to anyone reading the code.
No, I'd say that might be a bug. For example, if you import the static DateTime.Parse method, it works as you would expect. IPy appears to be placing the result if calling get_Now in the local scope, rather than the get_Now static method. I need to circle back with the team, but that seems wrong to me. I opened up a CodePlex bug for it. http://www.codeplex.com/IronPython/WorkItem/View.aspx?WorkItemId=16323
I have this simple code. But it returns an error: "TypeError: expected ProcessPriorityClass, got int" from System.Diagnostics import Process procs = Process.GetProcesses() for p in procs: if p.ProcessName == 'notepad': print p.BasePriority p.PriorityClass = 8 I thought one of the main points of ironpython is not have to worry about typing variables. But this seems to imply unless I do some sort of dim x as ProcessPriorityClass, I can't call set the value of PriorityClass. I have searched hard for the answer to this, but it seems like maybe IP isn't that widely used yet. If you have some good links to where to go to get more help with IP that would be nice. Thanks, Matt
IronPython is dynamically typed, but the underlying types from the .NET framework are still statically typed. IronPython won't auto convert an integer into an enumerated type, which is why you're getting a type exception. BasePriority is an integer, but it's read only. PriorityClass is read/write, but it takes a ProcessPriorityClass enum value. You could write the code this way: from System.Diagnostics import Process, ProcessPriorityClass procs = Process.GetProcesses() for p in procs: __if p.ProcessName == 'notepad': ____print p.BasePriority ____p.PriorityClass = ProcessPriorityClass.BelowNormal Note, I need to figure out how to get significant whitespace to work in comments. In the meantime, I'm using underscore as space in the code above.
Well that worked for me. It's actually pretty amazing what can be done with a few lines of code. As per your original topic, I did import Process from System.Diagnostics. I figured ProcessPriorityClass was part of Process. Is there a simple way to know what all is included when you import or try to import a .Net class. Thanks
Yep, use Python's built in dir function. You can also use the built-in help function to retrieve the built-in help and method signature for types and methods. from System import Diagnostics dir(Diagnostics.Process) dir(Diagnostics.Process.PriorityClass) help(Diagnostics.Process.GetProcesses)