Starting Python... some questions

J

jezonthenet

I started using Python a couple of days ago - here are a few
questions:

* Doesn't the __main__() method automatically execute when I run my
python program?
* Only when I do an import of my test.py file within python and then
run test.__main__() I can see where my bugs are. Is this correct?
(right now this is my only way of running my python program and see
where I have problems)
* Once I've done an import and then I wish to make a change to the
file I've imported I have to quit Python, restart and import that
module again in order for the module to be refreshed. Is there no "re-
import" ?
* Finally, could someone tell me why I'm having problems with the
small module below?
- Python pretends I provide chassis_id() with three parameters, even
though I clearly only provide it with two - why?

Thanks!

#!/usr/bin/python
import scapy
import struct

class lldp_class:
def __init__(self):
self.chassis_id_tlv = None

def chassis_id(subtype, chassis_info):
if subtype == 4:
chassis_data = struct.pack("!B",chassis_info)
subtype_data = struct.pack("!B",subtype)
self.chassis_id_tlv = subtype_data + chassis_data

def __main__():
p = lldp_class()
p.chassis_id(4, "01:80:C2:00:00:0E")
payload = p.chassis_id_tlv
ether = scapy.Ether(dst="01:02:03:04:05:06")
fullpayload = ether + payload
sendp(fullpayload)
 
J

Jordan Greenberg

I started using Python a couple of days ago - here are a few
questions:

* Doesn't the __main__() method automatically execute when I run my
python program?
* Only when I do an import of my test.py file within python and then
run test.__main__() I can see where my bugs are. Is this correct?
(right now this is my only way of running my python program and see
where I have problems)

No, there is no special __main__ function, to the best of my knowledge.
I think the idiom you're thinking of is:

if __name__="__main__":
#Your main stuff here

But that won't execute if you do an import. Only when you call the
script directly, like:

python myscript.py

for example.
* Once I've done an import and then I wish to make a change to the
file I've imported I have to quit Python, restart and import that
module again in order for the module to be refreshed. Is there no "re-
import" ?

There is. The reload command. Usage is similar to import:

import MyModule
#Do your edit, and reload thusly:
reload MyModule
* Finally, could someone tell me why I'm having problems with the
small module below?
- Python pretends I provide chassis_id() with three parameters, even
though I clearly only provide it with two - why?
Python expects self as the first parameter. You might want to take
another look at the class bits of your tutorial of choice, or:
http://docs.python.org/tut/node11.html

The function definition should look more like:

def chassis_id(self, subtype, chassis_info):

HTH.
-Jordan Greenberg
 
T

Thinker

-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1

I started using Python a couple of days ago - here are a few
questions:

* Doesn't the __main__() method automatically execute when I run my
python program?
* Only when I do an import of my test.py file within python and then
run test.__main__() I can see where my bugs are. Is this correct?
(right now this is my only way of running my python program and see
where I have problems)
* Once I've done an import and then I wish to make a change to the
file I've imported I have to quit Python, restart and import that
module again in order for the module to be refreshed. Is there no "re-
import" ?
* Finally, could someone tell me why I'm having problems with the
small module below?
- Python pretends I provide chassis_id() with three parameters, even
though I clearly only provide it with two - why?
No, Python is executing a module. You should explicit call __main__()
at top scope of
your module. For ex.

if __name__ == '__main__':
__main__()

This snippet calls __main__() when the module is executed directly,
but not imported as a module.

Once a module had been imported, you should invoke reload() function
to reload it from filesystem.


- --
Thinker Li - (e-mail address removed) (e-mail address removed)
http://heaven.branda.to/~thinker/GinGin_CGI.py
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.4.6 (FreeBSD)
Comment: Using GnuPG with Mozilla - http://enigmail.mozdev.org

iD8DBQFF9i/j1LDUVnWfY8gRAgidAKCxHUWf/XTuT8fRQmeL3hnsO4fohQCgt27R
jCNoz4hgp2CxD7H5HPwkfgM=
=4g/m
-----END PGP SIGNATURE-----
 
S

Steven D'Aprano

I started using Python a couple of days ago - here are a few
questions:

* Doesn't the __main__() method automatically execute when I run my
python program?


No.

* Only when I do an import of my test.py file within python and then
run test.__main__() I can see where my bugs are. Is this correct?
(right now this is my only way of running my python program and see
where I have problems)

That's a good way of choosing to run __main__ manually, but there are
other ways.

If you add a line to the end of your program:

__main__()


the function will be executed whenever the program runs. That is both when
you import it, and when you run it from the command line.

To ensure it doesn't run when you import, do this:


if __name__ == "__main__":
__main__()


* Once I've done an import and then I wish to make a change to the
file I've imported I have to quit Python, restart and import that
module again in order for the module to be refreshed. Is there no "re-
import" ?

Yes there is. Do this:

import my_module
# do things
# edit the file
# don't forget to save changes (that always catches me out)
reload(my_module)

* Finally, could someone tell me why I'm having problems with the
small module below?
- Python pretends I provide chassis_id() with three parameters, even
though I clearly only provide it with two - why?

Thanks!

#!/usr/bin/python
import scapy
import struct

class lldp_class:
def __init__(self):
self.chassis_id_tlv = None

def chassis_id(subtype, chassis_info):
if subtype == 4:
chassis_data = struct.pack("!B",chassis_info)
subtype_data = struct.pack("!B",subtype)
self.chassis_id_tlv = subtype_data + chassis_data

Class methods always take a first parameter that points to the
class instance. By convention, it should be called "self". So you should
write this as:

def chassis_id(self, subtype, chassis_info):
if subtype == 4:
chassis_data = struct.pack("!B",chassis_info)
subtype_data = struct.pack("!B",subtype)
self.chassis_id_tlv = subtype_data + chassis_data


When you call the method:

my_instance = lldp_class()
my_instance.chassis_id(4, "01:80:C2:00:00:0E")

Python automatically fills in a reference to the instance and calls this:

lldp_class.chassis_id(my_instance, 4, "01:80:C2:00:00:0E")


Just remember to always put "self" as the first argument to a class
method, and you will (almost never) go wrong!
 
B

Ben Finney

No, there is no special __main__ function, to the best of my
knowledge.

Guido van Rossum has mused on the idiom of the 'main' function in modules:

<URL:http://www.artima.com/weblogs/viewpost.jsp?thread=4829>

My idiom for this is:

=====
def __main__(argv=None):
""" Mainline code for this program """

from sys import argv as sys_argv
if argv is None:
argv = sys_argv

foo = Foo(argv) # Foo is the main thing I need
exitcode = None
try:
foo.do_the_main_thing()
except SystemExit, e:
exitcode = e.code

return exitcode

if __name__ == "__main__":
import sys
exitcode = __main__(argv=sys.argv)
sys.exit(exitcode)
=====

The reason for the local 'sys' imports is that I can boilerplate this
code and not have to worry about whether the rest of the program
actually uses the 'sys' module.

The reason for parameterising 'argv', but defaulting it to the system
argv, is that I can unit-test the '__main__' function
programmatically, while still letting it pick up the real argv when
the program is run.

Same reason for catching SystemExit, and then going on to call
'sys.exit()' myself: it allows the __main__ function to be unit-tested
easily, while still letting me use 'sys.exit()' in my application code
whenever it makes sense.

Now, when I write unit tests for my program (i.e. a Python module
designed to be run as a command), it can still be imported safely into
my unit tests, and all the code gets covered by test cases except the
three-line stanza at the end.
Htag.pl 0.0.23 - Simon Huggins <[email protected]> Released under GPL
Copyright (C) 1999-2002 Project Purple. http://www.earth.li/projectpurple/

Got sigmatch == ^/home/bignose/\.sigs/news.*$
 
B

Ben Finney

Ben Finney said:
Now, when I write unit tests for my program (i.e. a Python module
designed to be run as a command), it can still be imported safely
into my unit tests, and all the code gets covered by test cases
except the three-line stanza at the end.

All I need now is for Python to automatically execute a '__main__'
function if the module name is '__main__' (which it seems the OP
expected should happen), and unit test coverage could be 100% :)
Htag.pl 0.0.23 - Simon Huggins <[email protected]> Released under GPL
Copyright (C) 1999-2002 Project Purple. http://www.earth.li/projectpurple/

Got sigmatch == ^/home/bignose/\.sigs/news.*$

Er, okay. That was a bit strange. Sorry for the flubbed sigmonster.
 
T

Tim Roberts

You only need three things here:

#!/usr/bin/python
import scapy
import struct

class lldp_class:
def __init__(self):
self.chassis_id_tlv = None

def chassis_id(subtype, chassis_info):

Make that
def chassis_id(self, subtype, chassis_info):

When you call "p.chassis_id", "p" is passed as the first parameter to
chassis_id. By convention, we call that "self", in the same way the object
of a C++ method is called "this" (although that is enforced, rather than
convention).
if subtype == 4:
chassis_data = struct.pack("!B",chassis_info)
subtype_data = struct.pack("!B",subtype)
self.chassis_id_tlv = subtype_data + chassis_data

def __main__():

Make that
def main():

The underscores have a special meaning that you do not need here. Note
that the name "main" is not required; some people call it something like
"test".
p = lldp_class()
p.chassis_id(4, "01:80:C2:00:00:0E")
payload = p.chassis_id_tlv
ether = scapy.Ether(dst="01:02:03:04:05:06")
fullpayload = ether + payload
sendp(fullpayload)

Now, at the end, add:

if __name__=="__main__":
main()

That should do it.
 
B

Bruno Desthuilliers

(e-mail address removed) a écrit :
I started using Python a couple of days ago - here are a few
questions:

* Doesn't the __main__() method automatically execute when I run my
python program?

Which "__main__" method ???

Anyway, the answer is no. Every code at the top-level (which includes
import, class and def statements...) is executed when the module is
first loaded - whether as a proper module (ie: imported from somewhere
else) or as a main program (ie-> python mymodule.py). In the first case,
the special variable __name__ is set to the module's name, in the second
to '__main__'. So you can rely on this to have code executed when the
module is used as a program. The usual idiom is

# mymodule.py
(imports here)
(classes and defs here)

def main(argv):
(code of main function here)
return 0

if __name__ == '__main__':
import sys
sys.exit(main(sys.argv))

* Only when I do an import of my test.py file within python and then
run test.__main__()

BTW, you should *not* use names with 2 leadings and 2 trailing
underscores. These names are reserved for Python implementation stuff.
I can see where my bugs are. Is this correct?

Nope. You can also spot bugs by reading the code or running it thru the
debugger !-)

More seriously : using the above idiom (or any variant of - the
important part being the conditional on __name__ == '__main__'), you can
just
$ python mymodule.py

to run your program.
(right now this is my only way of running my python program and see
where I have problems)
* Once I've done an import and then I wish to make a change to the
file I've imported I have to quit Python, restart and import that
module again in order for the module to be refreshed. Is there no "re-
import" ?

reload(module_object)

But it's of very limited use. The best thing to do is usually to have a
simple test file that setup the desired state (imports etc) that you
execute after each change, passing the -i option to the python
interpreter (this will leave the interpreter in interactive mode after
execution of the test file, so you can inspect your objects, test things
etc).
* Finally, could someone tell me why I'm having problems with the
small module below?
- Python pretends I provide chassis_id() with three parameters, even
though I clearly only provide it with two - why?

Without even reading the code, I can tell you it's an instance or
classmethod with either a wrong declaration or wrongly called.
#!/usr/bin/python
import scapy
import struct

class lldp_class:

Do yourself a favor: use new-style classes. Also, it would be better to
stick to usual naming conventions (Python relies heavily on conventions):
http://www.python.org/dev/peps/pep-0008/

class Lldp(object):
def __init__(self):
self.chassis_id_tlv = None

def chassis_id(subtype, chassis_info):

Bingo. You need to have self as the first argument. The instance is
passed as the first argument of a method.

def chassis_id(self, subtype, chassis_info):
if subtype == 4:
chassis_data = struct.pack("!B",chassis_info)
subtype_data = struct.pack("!B",subtype)
self.chassis_id_tlv = subtype_data + chassis_data

def __main__():


def main():
p = lldp_class()
p.chassis_id(4, "01:80:C2:00:00:0E")

For the record: this is interpreted as:
lldp_class.chassis_id(p, 4, "01:80:C2:00:00:0E")

payload = p.chassis_id_tlv
ether = scapy.Ether(dst="01:02:03:04:05:06")
fullpayload = ether + payload
sendp(fullpayload)

if __name__ == '__main__':
main()

As a side note, it looks like there are a couple point where your design
may be improved. Like passing subtype and chassis_info to the __init__
of your class.

HTH
 
B

Bruno Desthuilliers

Steven D'Aprano a écrit :
No.



That's a good way of choosing to run __main__ manually, but there are
other ways.

If you add a line to the end of your program:

__main__()


the function will be executed whenever the program runs. That is both when
you import it, and when you run it from the command line.

To ensure it doesn't run when you import, do this:


if __name__ == "__main__":
__main__()




Yes there is. Do this:

import my_module
# do things
# edit the file
# don't forget to save changes (that always catches me out)
reload(my_module)



Class methods

s/Class/Instance/

classmethods are methods that takes the class as first parameter.
always take a first parameter that points to the
class instance.
(snip)

Just remember to always put "self" as the first argument to a class
method,

idem.
 
G

Guest

Ben said:
All I need now is for Python to automatically execute a '__main__'
function if the module name is '__main__' (which it seems the OP
expected should happen), and unit test coverage could be 100% :)

Short hint to go further:
exec file('/usr/lib/python2.4/timeit.py') in {'__name__': '__main__'}

nd
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,743
Messages
2,569,478
Members
44,899
Latest member
RodneyMcAu

Latest Threads

Top