Help using multiple .py files in one application

I am slowly attempting to create a basic shooter and to keep things more organised i wanted to have large sections of the code in seperate files.

What is the correct syntax for using multiple files? The code I am attempting to access from my ‘main.py’ file is at the moment just what is on http://panda3d.org/manual/index.php/Example_for_Clicking_on_3D_Objects

Any help would be appreciated.

You have a couple of options if you want to make use of a file in another file.

Python organizes code into “modules;” in general, the rule is “one module per file.” So let’s pretend you have two files, foo.py and bar.py. Foo contains class FooClass (which you’d like to use in bar.py) and class SomeOtherFooClass (which doesn’t need to be used in bar.py). To get what you want, you can do this in your bar.py file:

import foo

myInstance=foo.FooClass()

Note that importing in this way wraps the FooClass in a namespace (actually, a module object) named foo, which you have to access using the dot-syntax, like an object.

Another option is to pull the element you want from foo directly into your namespace. To do that, use syntax like this:

from foo import FooClass

myInstance=FooClass()

Now FooClass is actually in the bar module. This has two side effects: first, you no longer have to access FooClass through the foo module, and secondly, if someone else were to come along and import bar, they could now access bar.FooClass.

There’s a third option (the ‘nuclear option,’ if you will), but I don’t recommend it except in some special cases. That is to use the wildcard to import everything in a module:

from foo import *

myInstance=FooClass()  #we imported FooClass...
secondInstance=SomeOtherFooClass() # ... but we also grabbed this class!

Wildcard can be a useful shortcut, but conceptually it means something important: it breaks the module abstraction between foo and bar. In other words, there is now a contract between bar and foo that looks something like this: “My bar module is so intimately connected to the foo module that I am going to trust that you will never add any more symbols (functions, classes, or global variables) to foo that could interfere with my symbols in bar.” Usually, that’s not the level of connection you want, but it can be useful at times… I usually just go “from pandac.PandaModules import *” instead of pulling in specific pieces, because (a) PandaModules is huge and (b) I’m writing a Panda program, so I probably do want the opportunity to touch every class in the manual :wink:.

There are higher level concepts (like packags, so you can put your source in a folder named ‘baz’ and get to it by saying “from baz.foo import FooClass”). But the stuff above will get you started. Ask again if you want more detail.

Best of luck!

Take care,
Mark

There is another option. I like to use aliasing.

from pandac import PandaModules as P

The keyword [color=blue]as lets me avoid the nuclear * option, but lets me type the names almost as easily: e.g.

P.Vec3(0,0,0)

Plus I can always tell where the class came from, wich makes it easier to learn a new library.

Another point: Python only looks for modules in the current directory, on the PYTHONPATH, and usually where python was installed. As long as you keep your modules in the same directory as your importing script you should be fine.

Also note that when you start importing modules python will automatically try to compile them into python bytecode .pyc. (This doesn’t erase the .py files) to help them to import faster.

Thanks for the replys guys - very useful.

Mark, one question though: with importing things how do i properly call the function. For example with the file posted in the first post how would i properly call mousePicker.makePickable(box) (Making ‘box’ pickable)from the main file?

Would it be like this?

import picker 

myPicker=picker.makePickable()

myPicker.picker.makePickable(box)

Thanks for the help.

Let’s assume you saved the Picker class code in a file called picker.py and can import it with:

import picker

you would first have to create a picker object.

myPicker = picker.Picker()

Once you have that object, you have access to all of its functions defined in the Picker class and you no longer need to use ‘picker’ to resolve them. You simply use your instance of the Picker class.

myPicker.makePickable(box)

A good book to pick up on a lot these concepts is O’Reilly’s “Learning Python” http://www.oreilly.com/catalog/lpython/