Register a SA Forums Account here!
JOINING THE SA FORUMS WILL REMOVE THIS BIG AD, THE ANNOYING UNDERLINED ADS, AND STUPID INTERSTITIAL ADS!!!

You can: log in, read the tech support FAQ, or request your lost password. This dumb message (and those ads) will appear on every screen until you register! Get rid of this crap by registering your own SA Forums Account and joining roughly 150,000 Goons, for the one-time price of $9.95! We charge money because it costs us money per month for bills, and since we don't believe in showing ads to our users, we try to make the money back through forum registrations.
 
  • Locked thread
bitprophet
Jul 22, 2004
Taco Defender
Sorry if you did get this already, The CRAIGGERS, but Python's pass-by-value/reference is sort of funky: it's actually all about mutability. (At least, in my understanding...)

So, for example, strings are immutable; you can never operate on a string and change it, you can only get back a copy of the string with the change applied. So if you pass a string into a function, it's effectively pass by value, because you can't actually "do" anything to the string that will have an effect in the calling scope.

Lists are mutable; if you update a list member, you're changing the actual list, and not a copy of it. Thus, if you pass a list into a function, it's effectively pass by reference. Modifying the list inside the function will thus be seen in the calling scope after the function returns (because both names are references to the same object in memory).


About the module scope deal, JoeNotCharles is totally right, what you're asking for would be very un-Pythonic Python (if it were actually possible, which it is not AFAIK). Python tries to be clean and explicit and encourage good behavior (while still generally staying out of your way, it's no Java or anything) so generally its language rules try to keep some level of sanity.

Note that you can read all of Python's rules in the docs, and as a C coder most of the terminology should be old hat to you (as Python is written in C itself, the core team tends to write for an audience that might also know C or similar languages). The language reference might help.

Adbot
ADBOT LOVES YOU

Peg Pelvis Pete
May 2, 2004

I LIKE MATH!!!
What is the most elegant way to create a 2-dimensional "matrix" (list of lists) filled with None? I tried
code:
>>> width, height = 4, 4
>>> M = [[None]*width]*height
But that causes the following situation:
code:
>>> for y in xrange(height):
...     M[y][0] = y
...
>>> M
[[3, None, None, None], [3, None, None, None], [3, None, None, None], [3, None, None, None]]
After a few hours I figured out that it was the way it was declared that was doing this. I had made M into a list of references to the same list. So anyway, that's out the window. How can I modify this to declare an empty matrix?

Scaevolus
Apr 16, 2007

Peg Pelvis Pete posted:

After a few hours I figured out that it was the way it was declared that was doing this. I had made M into a list of references to the same list. So anyway, that's out the window. How can I modify this to declare an empty matrix?
code:
>>> width, height = 4, 4
>>> M = [[None]*width for _ in xrange(height)]
>>> M
[[None, None, None, None], [None, None, None, None], 
 [None, None, None, None], [None, None, None, None]]
>>> M[0][1]=4
>>> M
[[None, 4, None, None], [None, None, None, None], 
 [None, None, None, None], [None, None, None, None]]
If you're doing lots of stuff with multidimensional arrays, you should look into NumPy.

The CRAIGGERS
Mar 3, 2006
I am foo incarnate!

JoeNotCharles posted:

Why would or should a module be able to access variables from it's caller? If you're going to kill reusability like that, why bother putting things in a separate module at all?

That was actually my friend. I guess he had a massive C library of modules and he just used some globals for switches from the command line or something. To be honest I was less of a fan of that approach than the passing-the-dict idea.

bitprophet posted:

So, for example, strings are immutable; you can never operate on a string and change it, you can only get back a copy of the string with the change applied. So if you pass a string into a function, it's effectively pass by value, because you can't actually "do" anything to the string that will have an effect in the calling scope.

Lists are mutable; if you update a list member, you're changing the actual list, and not a copy of it. Thus, if you pass a list into a function, it's effectively pass by reference. Modifying the list inside the function will thus be seen in the calling scope after the function returns (because both names are references to the same object in memory).

This along with JoeNotCharles' xyz example actually helped me out a bit. Thanks. Since I'm still trying to get what is un-Pythonic, what is more normal? Passing a list as a parameter and updating it, or returning a list of values as in the xyz example? I'm sure there are good uses for both; I'm just trying to get a handle on what is "Pythonic" (to borrow the new term).

Scaevolus
Apr 16, 2007

The CRAIGGERS posted:

Don't worry about passing dictionaries into other things; this is a common and accepted practice, especially with templating systems, where you pass in a dictionary of the variables that the template uses to render.

Have you read through the official python tutorial? It might clear up some of these questions.

JoeNotCharles
Mar 3, 2005

Yet beyond each tree there are only more trees.

The CRAIGGERS posted:

I'm just trying to get a handle on what is "Pythonic" (to borrow the new term).

http://www.python.org/dev/peps/pep-0020/

tef
May 30, 2004

-> some l-system crap ->
Often if you have some mutable data structure, which have a number of functions that operate on it, it's easier to make it a class.

I would also advocate reading through the python tutorial.

http://docs.python.org/tutorial/index.html

Peg Pelvis Pete
May 2, 2004

I LIKE MATH!!!

Scaevolus posted:

code:
>>> width, height = 4, 4
>>> M = [[None]*width for _ in xrange(height)]
>>> M
[[None, None, None, None], [None, None, None, None], 
 [None, None, None, None], [None, None, None, None]]
>>> M[0][1]=4
>>> M
[[None, 4, None, None], [None, None, None, None], 
 [None, None, None, None], [None, None, None, None]]
If you're doing lots of stuff with multidimensional arrays, you should look into NumPy.

Thanks, this is exactly the sort of one-liner I was looking for.

The CRAIGGERS
Mar 3, 2006
I am foo incarnate!

Scaevolus posted:

Don't worry about passing dictionaries into other things; this is a common and accepted practice, especially with templating systems, where you pass in a dictionary of the variables that the template uses to render.

Have you read through the official python tutorial? It might clear up some of these questions.

Thanks. Yeah, I've read through most of the tutorial. At least the first few chapters to get a handle on things. I figured I would save some of the more in-depth stuff for when I'm stuck on a particular problem and have the motivation to dive into it once again.

Thanks for everyone's help. Now I can start playing with XML libraries.

Id4ever
Dec 2, 2004
When writing apps in Python, I often wrap my main() function with a try..except statement that catches any unhandled exceptions (except KeyboardInterrupt) and writes the stack trace to a log file. However I'm thinking that being able to inspect variables when this happens would sometimes be very helpful in uncovering the cause of bugs.

If I run locally I can always invoke pdb in the event of an uncaught exception, but if my app is running on someone else's computer I don't really have that option. Instead I would like to do a full dump of all stack frames including variable values to file. The person that experiences the crash can then send me the file for post-mortem debugging, similar to loading a core dump into gdb.

I've noticed the pdb.post_mortem([traceback]) function, but I'm not really sure if this would accomplish my goal. In any case I haven't found a way of saving a traceback in one interpreter instance and loading it in another. Has anyone ever tried something like this before?

Id4ever fucked around with this message at 22:49 on Nov 1, 2008

Thats so Brad!
Jul 5, 2008

by Ozma
code:
import sys

# Starting menu system

def menu():
    choice = 0
    loop = 1
    print 'CYOA program test'
    print ''
    print 'Choose your option:'
    print ''
    print '1) Start a new game'
    print '2) Load a saved game'
    print '3) Exit'
    while loop == 1:
        choice = input('->')
        if choice == 1:
            newgame()
            loop = 0
        elif choice == 2:
            loadgame()
            loop = 0
        elif choice == 3:
            sys.exit()
        else:
            print 'Not an option.'

class room:
    name = 'Unnamed.'
    desc = 'Undescribed.'

def roomfunc(room):
    print room.name
    print room.desc

# Room pool:
room1 = room
room1.name = 'The first room'
room1.desc = 'description of the first room'

room2 = room
room2.name = 'Second'
room2.desc = 'second.'

# Start a new game, starting the room function that activates the first room.

def newgame():
    print 'Starting a new game.'
    print ''
    print 'Game begins.'
    print ''
    print 'Game intro'
    print ''
    roomfunc(room1)

menu()
This is my first time with any programming language so I figured i'd try to make a short, choose your own adventure game. There's something wrong with my coding though because the roomfunc function immediately skips into room2 when there doesn't seem to be any code telling it to do so. Does anyone see the problem?

Lonely Wolf
Jan 20, 2003

Will hawk false idols for heaps and heaps of dough.
You're not instantiating your room objects. It needs to be room1 = room(), etc. However, you're going to have far more problems than that. You should probably read up on classes and objects in the Python tutorial.

duck monster
Dec 15, 2004

Yeah whats happening is your pointing room1 and room2 at the same class by pointer

its sort of saying

room1 IS room
room2 ALSO IS room

the problem here is that when you set room2.name, your actually refering to room.name which is the same thing as room1.name

this is wrong!

What you want is;-

room1 IS A room
room2 IS ALSO A room

to do this you do you do this

room1=room()

room2=room()

Whats happening here is that calling the room object as a function will
A) Create a new INSTANCE of the room object
B) call the __init__() function of the object (if it has one)
and finally
C) poo poo out a pointer to the object into your room1 variable

kinda

Can I also make a suggestion.

Rather than Room1 room2 room3 etc

Try
roomArray={}
roomArray[1] = room()
roomArray[2] = room()
and so on...

That way you can go

myRoom=roomArray[roomNo]

and it'll always return the right room

edit:

:toot:

code:

class room:
   ...
   doorNames = {}
   doorDest = {}
   def setDoor(self,doorNo,doorName,doorDest)
       self.doorNames[doorNo] = doorName
       self.doorDest[doorNo]  = doorDest

   def showDoorNames(self):
       for door in in self.doorNames:
             print "Door #"+str(door)+" : "+str(self.doorNames[door])
   def getDoorDest(self,doorNo):
             return self.doorDest[doorNo]
 


roomArray[3] = room()
roomArray[3].description = "A room with some stuff in it"
roomArray[3].setDoor(1,'Door East',5)
roomArray[3].setDoor(2,'Door South',1)
roomArray[5] = room()
roomArray[5] = "Hi look its some other room ok?"
(etc)

myRoom = roomArray[3]
print myRoom.description

   A room with some stuff in it

myRoom.showDoors()

    Door #1 : door east
    Door #2 : door south

myroom = roomArray[myRoom.getDoorDest(1)]
print myRoom.description

   Hi look its some other room ok?

Untested, but theres some ideas for ya. Try and push as much logic about how a room behaves into the room itself. Theres a few ways of doing this , and none are really the right way.

You can have a self representing room, so when you go

myRoom.look(), it'll poo poo out a full description of the room, and the doors and everything.

Alternatively you can get a bit more MVC, and have a room that contains a MODEL of the room and how it kinda works , but doesnt represent it to the user. thats done by other code (for instance a showRoom(room) function like you have).

Theres a few other ways too. Look up "design patterns". Most are loving worthless poo poo java programmers torture themselves with to make up for the languages contortions, but theres a few great ones as well that are worth learning.

duck monster fucked around with this message at 21:43 on Nov 2, 2008

m0nk3yz
Mar 13, 2002

Behold the power of cheese!
Oh no guys, I've picked up "Programming Erlang" - I'm going to the dark side :jihad:

Of course, this is all part of my clever plot to introduce Actors/Message passing pieces to python.

duck monster
Dec 15, 2004

m0nk3yz posted:

Oh no guys, I've picked up "Programming Erlang" - I'm going to the dark side :jihad:

Of course, this is all part of my clever plot to introduce Actors/Message passing pieces to python.

shave that beard son

king_kilr
May 25, 2007

m0nk3yz posted:

Oh no guys, I've picked up "Programming Erlang" - I'm going to the dark side :jihad:

Of course, this is all part of my clever plot to introduce Actors/Message passing pieces to python.

Guido said that he though Actors were one of the "right ways" to do concurency. It's somewhere in

http://moderator.appspot.com/#e%253Dagltb2RlcmF0b3JyDQsSBlNlcmllcxjJAQw%252Bt%253Dagltb2RlcmF0b3JyDAsSBVRvcGljGP8BDA%252Bv%253D15

m0nk3yz
Mar 13, 2002

Behold the power of cheese!

king_kilr posted:

Guido said that he though Actors were one of the "right ways" to do concurency. It's somewhere in

http://moderator.appspot.com/#e%253Dagltb2RlcmF0b3JyDQsSBlNlcmllcxjJAQw%252Bt%253Dagltb2RlcmF0b3JyDAsSBVRvcGljGP8BDA%252Bv%253D15

Yup. He said it in response to the multi core question:

quote:

I think the panic is greatly exaggerated. We are *not* all going to have to write multi-threaded programs all the time. It would slow productivity to a grinding halt anyway, due to the extreme difficulty of writing correct concurrent code using the current crop of mechanisms. As we get more cores, the cost of accessing memory that's shared between multiple threads is only going to increase relative to the cost of accessing unshared (cache) memory, and message passing will become a much more appropriate paradigm than shared memory and critical sections.

Python 2.6 and 3.0 are including a new package, multiprocessing, which makes creation of and communication between multiple processes as simple as managing threads was in Python 2.5, and my expectation is that something not entirely unlike the Actor paradigm, but implemented on top of the multiprocessing package, will eventually become the recommended best practice for reaping the benefits of multiple cores. Each process will be self-contained and only communicate with others at specific times when it sends or receives a message.

And you can also see my intentions in this post to python-dev:
http://mail.python.org/pipermail/python-dev/2008-October/083244.html

So, while Erlang's syntax makes me about as excited as punching myself in the face, I'd rather know more about the Actor system as implemented in it.

Just to add: One of the big drawbacks to the multiprocessing package is IPC - the serialization/de-serialization costs can harm you if you're passing crap-tons of objects, not to mention the basic requirement of pickle-ability. Erlang's actors are not independent processes.

m0nk3yz fucked around with this message at 22:53 on Nov 2, 2008

ATLbeer
Sep 26, 2004
Über nerd

m0nk3yz posted:

Oh no guys, I've picked up "Programming Erlang" - I'm going to the dark side :jihad:

Of course, this is all part of my clever plot to introduce Actors/Message passing pieces to python.

code:
1> X = 6.
6
2> X = 7.
** exception error: no match of right hand side value 7
Erlang is another planet

m0nk3yz
Mar 13, 2002

Behold the power of cheese!

ATLbeer posted:

code:
1> X = 6.
6
2> X = 7.
** exception error: no match of right hand side value 7
Erlang is another planet

Yup, see above: I really don't like the syntax. I'm mainly interested in the concurrency primitives/etc. I've never been a fan of functional programming.

Also:

duck monster posted:

shave that beard son

I can't even grow one much less shave one. Although I have been considering suspenders.

tef
May 30, 2004

-> some l-system crap ->
Edit: Should refresh before posting.

hey mom its 420
May 12, 2007

ATLbeer posted:

code:
1> X = 6.
6
2> X = 7.
** exception error: no match of right hand side value 7
Erlang is another planet
Well, first you said X was 6 and then you said it was 7. Are you some kind of liar?

tef
May 30, 2004

-> some l-system crap ->

mr noller posted:

Imagine a concurrent package for python: in it you have your basics - threading, multiprocessing (maybe "acting" too, but that name sucks,
how about greenprocesses? :)) and you also have utilities like
multiprocessing.pool, multiprocessing.manager/etc,
threading.producer_consumer, etc. We build these out and make them "as
safe as possible".

Aside, light weight processes are often called Fibers.

quote:

So, while Erlang's syntax makes me about as excited as punching myself in the face, I'd rather know more about the Actor system as implemented in it.

There is more to erlang than just the message passing concurrency though, and I would really suggest looking at it in depth for some of the other details. OTP is really geared towards making robust applications.

One of the things is that when a process dies, it sends a termination message to it's parents - that if uncaught, forces them to die too. If nothing matches in a case expression, an error is thrown too.

There are also inherent limitations to erlangs model too. There is only one 'inbox' per process and no way to seperate out messages in advance. This means if you are not careful it is a linear scan to find any high priority messages first.

See this post for an example: http://www.lshift.net/blog/2007/10/01/too-much-mail-is-bad-for-you

quote:

Just to add: One of the big drawbacks to the multiprocessing package is IPC - the serialization/de-serialization costs can harm you if you're passing crap-tons of objects, not to mention the basic requirement of pickle-ability. Erlang's actors are not independent processes.

It is not just because erlang is independant, but because it is also pure that allows it's message passing to be so cheap. They don't have to copy any data or maintain synchronization.

Singularity manages to make message passing cheap by enforcing uniqueness. Only one process can use shared memory at a time, and when anything is sent the original process loses ownership.

Although erlang is flavour of the month, there are a couple of other interesting approaches to concurrency, notably the join calculus

Thats so Brad!
Jul 5, 2008

by Ozma
code:
import sys

# Starting menu system

def menu():
    choice = 0
    loop = 1
    print 'CYOA program test'
    print ''
    print 'Choose your option:'
    print ''
    print '1) Start a new game'
    print '2) Load a saved game'
    print '3) Exit'
    while loop == 1:
        choice = input('->')
        if choice == 1:
            game()
            loop = 0
        elif choice == 2:
            loadgame()
            loop = 0
        elif choice == 3:
            sys.exit()
        else:
            print 'Not an option.'

# A scene contains its name, description, and a list of choices for the
# reader to take. The reader then inputs the number corresponding to his
# choice of action. That number then determines which scene he moves to.

class scene:
    name = 'name'
    desc = 'desc'
    choices = []
    choice = 0

def scenefunc(scene):
    scene.choice = 0
    print scene.name
    print ''
    print scene.desc
    print ''
    print 'What do you do?'
    for entry in scene.choices:
        print 1 + scene.choices.index(entry),
        print ') ' + entry
    while scene.choice == 0:
        scene.choice = input('->')
    scenefunc(sceneArray[scene.choice])
    

# scene pool:
sceneArray={}
sceneArray[0]=room()
sceneArray[0].name = 'Starting Room'
sceneArray[0].desc = 'The starting room.'
sceneArray[0].choices = ['1','2']

sceneArray[1]=room()
sceneArray[1].name = 'Second Room'
sceneArray[1].desc = 'The second room.'
sceneArray[1].choices = ['']

sceneArray[2]=room()
sceneArray[2].name = 'Second Room alt'
sceneArray[2].desc = 'The second room alternative.'
sceneArray[2].choices = ['']

# Start a new game, starting the room function that activates the first room.

def game():
    print 'Starting a new game.'
    print ''
    print 'Game begins.'
    print ''
    print 'Game intro'
    print ''
    scenefunc(sceneArray[0])

menu()
Ok i did things differently this time but it's still a confusing mess. At least it's helping me learn more about the interaction between functions, classes, and tuples. I feel like I almost understand how coding works now, at least a lot more than back when I tried to learn C++ from scratch.

The CRAIGGERS
Mar 3, 2006
I am foo incarnate!
Hey, me again. I've been reading up on comparing lists and everything I've read thusfar says that this should not be happening:
code:
print Players , CheckedInPlayers, Players.sort() == CheckedInPlayers.sort()
returns:
code:
['Test Person', 'TheCraiggers', 'TheCraiggersasf'] ['Test Person', 'TheCraiggers'] True
In case you can't tell, I have two strings stuffed in Players and three strings stuffed into CheckedInPlayers. For some reason it thinks these two lists are equal. I even changed the order of the equality test around just in case it was only comparing the first two because there were only two in the first list. What craziness is this?

Scaevolus
Apr 16, 2007

The CRAIGGERS posted:


code:
>>> a = [3,4,1]
>>> a.sort() == a
False
>>> a.sort() == a
False
>>> a
[1, 3, 4]
>>> sorted(a) == a
True
list.sort doesn't return anything-- it just modifies the list in place. You want to do sorted(Players) == sorted(CheckedInPlayers).

Habnabit
Dec 30, 2007

lift your skinny fists like
antennas in germany.

Id4ever posted:

When writing apps in Python, I often wrap my main() function with a try..except statement that catches any unhandled exceptions (except KeyboardInterrupt) and writes the stack trace to a log file. However I'm thinking that being able to inspect variables when this happens would sometimes be very helpful in uncovering the cause of bugs.

If I run locally I can always invoke pdb in the event of an uncaught exception, but if my app is running on someone else's computer I don't really have that option. Instead I would like to do a full dump of all stack frames including variable values to file. The person that experiences the crash can then send me the file for post-mortem debugging, similar to loading a core dump into gdb.

I've noticed the pdb.post_mortem([traceback]) function, but I'm not really sure if this would accomplish my goal. In any case I haven't found a way of saving a traceback in one interpreter instance and loading it in another. Has anyone ever tried something like this before?

This is more difficult than you'd think from within python because there is no simple way to save the state of the interpreter. Frame objects can't be marshaled or pickled, and trying to write a pickler for one becomes complicated rather quickly because there's quite a few things you can't pickle.

I think there's macros to jump into pdb from a gdb stack trace, but I'm not entirely sure if they exist or are entirely usable. I've heard rumors about it, but nothing definite. There's os.abort() for dumping core, if you want to try that out.

The CRAIGGERS
Mar 3, 2006
I am foo incarnate!

Scaevolus posted:

list.sort doesn't return anything-- it just modifies the list in place. You want to do sorted(Players) == sorted(CheckedInPlayers).

Crap! You know, I read that sort didn't return anything somewhere while I was researching this problem and it just never dawned on me to put 1 and 1 together. For some reason I never tried to do a print Players.sort(); that would have told me what was up. Thanks for answering yet another boring question from me.

chemosh6969
Jul 3, 2004

code:
cat /dev/null > /etc/professionalism

I am in fact a massive asswagon.
Do not let me touch computer.
What's the easiest way to connect to a SSH system and send commands such as to a menu that comes up after logging in. Nothing more complicated than sending numbers and such.

tef
May 30, 2004

-> some l-system crap ->
use expect + ssh.

alternatively, use the subprocess module to launch ssh, and manipulate it

m0nk3yz
Mar 13, 2002

Behold the power of cheese!

tef posted:

use expect + ssh.

alternatively, use the subprocess module to launch ssh, and manipulate it

And if you really want to do it "right" - use Paramiko. But that's overkill if all you want is something silly. See also http://www.theether.org/pssh/

Janitor Prime
Jan 22, 2004

PC LOAD LETTER

What da fuck does that mean

Fun Shoe
I have an OO question regarding Python. From what I've read Python doesn't have anything like Abstract classes so it also doesn't have interfaces in the Java/C++ sense.

In my class diagrams I have multiple classes that implement an interface. Should I just create a Class with blank methods and have those other classes inherit it?

hey mom its 420
May 12, 2007

No need to. Just implement the methods from the interface in those classes and then call them to your heart's content. That's what duck typing is.
For instance, several classes in Python implement the methods from the file class, meaning they can act like files, but they aren't subclasses of any particular class just because of that.
Python 3000 offers abstract base classes but even in Python 3000, I'd still suggest just implementing the methods.

bitprophet
Jul 22, 2004
Taco Defender
What he said. Abstract classes and interfaces are just baggage a language can use to add extra layers of safety, at the cost of development time and probably execution/compile time too. In languages like Java/C++, which fall towards the safety end of the spectrum, they're a useful tool because that's the mindset you're working in.

But in Python and other "agile" languages, which take the other side of the tradeoff (trust your coders to do things the right way and don't tie them down with as many rules) such things are generally frowned upon because, again, that's just not how you write Python, and it adds unnecessary time/effort to your development.

A couple of high profile projects such as Twisted and Trac make heavy use of Java-isms like interfaces, and -- surprise, surprise -- they can be a pain in the rear end to work with and certainly do not feel like real Python code much of the time.

If you're dead set on using such tools in Python (again, we recommend you just use duck typing -- implement the actual methods of the interface, but don't bother coming up with a way to enforce/advertise it) the library that seems to be used the most is a Zope originated one called zc.Interface, I think. Look at the programmer's guides for Twisted or Trac and they should mention it early on.

bitprophet fucked around with this message at 23:55 on Nov 5, 2008

hey mom its 420
May 12, 2007

That's why Python and Ruby rely on automated testing much more than languages with compile-time type safety.

TOO SCSI FOR MY CAT
Oct 12, 2008

this is what happens when you take UI design away from engineers and give it to a bunch of hipster art student "designers"

MEAT TREAT posted:

I have an OO question regarding Python. From what I've read Python doesn't have anything like Abstract classes so it also doesn't have interfaces in the Java/C++ sense.

In my class diagrams I have multiple classes that implement an interface. Should I just create a Class with blank methods and have those other classes inherit it?

A common pattern I see for implementing abstract classes in Python is to define the methods in the superclass, but the method bodies are simply "raise NotImplementedError". Code-checking tools like Pylint special-case this, and can verify that subclasses implement their parents methods.

I even do this for purely-abstract / interface classes, for documentation reasons. It's nice to be able to see a description of what interfaces should act like in the documentation. Some programmers prefer to leave the interfaces defined only in the documentation and let incomplete subclasses fail with AttributeError, but I think NotImplementedError provides a nicer hint to the programmer about what's going on.

BigRedDot
Mar 6, 2008

quote:

I even do this for purely-abstract / interface classes, for documentation reasons.
We did this at the python shop I worked at and frankly I am appalled that anyone would think that doing so is a bad idea or "unpythonic". Python just by its nature demands more diligence with documentation, especially for very large collaborative projects (such as we developed).

chemosh6969
Jul 3, 2004

code:
cat /dev/null > /etc/professionalism

I am in fact a massive asswagon.
Do not let me touch computer.

tef posted:

use expect + ssh.

alternatively, use the subprocess module to launch ssh, and manipulate it

I'm trying to use subprocess and I have no problem getting the program going but I'm not sure what I need to do to get the program to start taking input, if I can even do that.


code:
proc = subprocess.Popen('f:\\putty username@server -pw password',
                        shell=True,
                        stdin=subprocess.PIPE,
                        )
proc.communicate('2\n')
I also tried using paramiko and the demo_simple.py example. When I run that, I get logged in fine and am at the menu but I still can't figure out how to send a '1' which is the command to exit the menu and get to the shell.

Any ideas on sending commands either way?

bitprophet
Jul 22, 2004
Taco Defender

BigRedDot posted:

We did this at the python shop I worked at and frankly I am appalled that anyone would think that doing so is a bad idea or "unpythonic". Python just by its nature demands more diligence with documentation, especially for very large collaborative projects (such as we developed).

Right, and if you're using the NotImplementedError bit as documentation, that's fine (especially if the superclass is its own class and isn't an empty abstract class, IMO) -- and other folks might choose to only use literal text documentation saying "ok we have this type of API that classes can implement".

It's the thought that you must have fully abstract interfaces in order to Get Stuff Done that's un-Pythonic, in my opinion.

tef
May 30, 2004

-> some l-system crap ->

chemosh6969 posted:

code:
proc = subprocess.Popen('f:\\putty username@server -pw password',
                        shell=True,
                        stdin=subprocess.PIPE,
                        )
proc.communicate('2\n')

Try:

code:
import subprocess
proc = subprocess.Popen(['[b]f:\\plink[/b]','username@server','-pw','password'],
                        shell=True,
                        stdin=subprocess.PIPE,
                        stdout=subprocess.PIPE,
                        )
proc.stdin.write('2\n')
print proc.stdout.read()
?

You have to specify PIPE for each file handle you wish to control, otherwise it inherits the parent's by default.

Putty is a GUI program, and not a terminal program. As such it is hard to control the input and output. What you want instead is plink or ssh which are console/terminal programs.

Plink is part of the putty distribution, and is documented here: http://the.earth.li/~sgtatham/putty/0.60/htmldoc/Chapter7.html#plink

Adbot
ADBOT LOVES YOU

BigRedDot
Mar 6, 2008

quote:

It's the thought that you must have fully abstract interfaces in order to Get Stuff Done that's un-Pythonic, in my opinion.
Fair enough, I'm really only talking about projects of a certain size.

  • Locked thread