Re: [Tutor] Py 2.4.4: Inheriting from ftplib.FTP()
On Thu, Jun 16, 2016 at 10:38:13AM -0500, boB Stepp wrote: > I am extremely gradually trying to dip my big toe into the waters of > writing classes. [...] > What I learned today: > > 1) FTP from ftplib appears to be an old-style class. > > 2) I can't just use "class FTPFiles(FTP)" or I will be using old-style > classes. > > 3) I need to use "class FTPFiles(FTP, object)" to use new-style > classes and "object" must come AFTER "FTP". > > 4) I have to use "super(FTPFiles, self).__init__(host, user, passwd)" > or I cannot successfully inherit from the FTP() class. Also, "self" > apparently must come AFTER "FTPFiles" in the super expression. > > Questions: > > 1) Are there any more common "gotchas" that might be coming my way in > trying to use a new-style class inheriting from an old-style class in > ancient Py 2.4.4? That's a very interesting question. I *think* the answer is "No", but I wouldn't put money on it. > 2) I don't have much knowledge about FTP processes. This is being > used on a secure intranet environment. And I am using the ftplib for > the first time. In its docs it mentioned that the quit() method is > the "polite" way to close the connection, but that an exception may be > raised if the responds with an error to the "QUIT" command the method > sends. If this happens, will the connection close? According to the source code, yes. > Or should I do something like: > > try: > ftp.quit() > except: > ftp.close() > > ? It seems here (If I should use the "try" block.) that a bare > "except" is appropriate as I would think I would want to close the > connection regardless of the type of error the "QUIT" command > generates. Bare except is nearly never appropriate. Consider: try: fpt.quit() except: ftp.close() > 3) The point of the print_welcome_msg() method is to be sure that I > have actually successfully connected to the FTP server. Is there a > better way to check for connection success? If the connect method doesn't raise an exception, it connected successfully. -- Steve ___ Tutor maillist - Tutor@python.org To unsubscribe or change subscription options: https://mail.python.org/mailman/listinfo/tutor
Re: [Tutor] Py 2.4.4: Inheriting from ftplib.FTP()
Some futher thoughts: On Thu, Jun 16, 2016 at 10:38:13AM -0500, boB Stepp wrote: > class FTPFiles(FTP, object): > """FTP files to Windows server location(s).""" > > def __init__(self, host=server_ip, user=user, passwd=passwd): > """Initialize FTPFiles object. Normally the defaults will be used.""" > > super(FTPFiles, self).__init__(host, user, passwd) > self.host = host > self.user = user > self.passwd = passwd Do you actually need to record these? Once they're used to establish a connection and login, what are they for? > def print_welcome_msg(self): > """Print welcome message sent by FTP server.""" > print self.getwelcome() The getwelcome method already prints the message, which is a bad design. But only if debugging is true. So I would approach this in one of two ways: (1) Delegate to the existing getwelcome method: def print_welcome_msg(self): save_flag = self.debugging self.debugging = True try: x = self.getwelcome() # prints the msg finally: self.debugging = save_flag (2) Re-implement the print functionality. def print_welcome_msg(self): print "*welcome*", self.welcome (3) If you really want to be paranoid, use: print "*welcome*", self.sanitize(self.welcome) although I don't think it's likely to make any real difference in practice. (The sanitize method makes a feeble attempt to hide the password.) > if __name__ == '__main__': > ftp = FTPFiles() > ftp.print_welcome_msg() > ftp.quit() This appears to be equivalent to: ftp = FTP(host, user, passwd) ftp.debugging = True x = ftp.getwelcome() ftp.quit() > What I learned today: > > 1) FTP from ftplib appears to be an old-style class. > > 2) I can't just use "class FTPFiles(FTP)" or I will be using old-style > classes. Is this a problem? Old-style classes are good enough for many purposes. > 3) I need to use "class FTPFiles(FTP, object)" to use new-style > classes and "object" must come AFTER "FTP". > > 4) I have to use "super(FTPFiles, self).__init__(host, user, passwd)" > or I cannot successfully inherit from the FTP() class. Also, "self" > apparently must come AFTER "FTPFiles" in the super expression. For old-style classes, don't use super because it doesn't work. Instead just write: FTP.__init__(self, host, user, passwd) That means that you cannot engage in multiple inheritence with new-style classes, but MI is a serious pain to get right, and 99% of the time it is overkill, so you're not missing much. -- Steve ___ Tutor maillist - Tutor@python.org To unsubscribe or change subscription options: https://mail.python.org/mailman/listinfo/tutor
Re: [Tutor] Py 2.4.4: Inheriting from ftplib.FTP()
On Thu, Jun 16, 2016 at 11:40 AM, Alan Gauld via Tutor wrote: > On 16/06/16 16:38, boB Stepp wrote: > >> class FTPFiles(FTP, object): >> """FTP files to Windows server location(s).""" > > OK, First comment. You describe this as an action(verb) > rather than a noun. Classes should represent nouns > (objects) not actions. FTP represents a protocol > connection with which you can do things (one of > which is put/get files) you class should be the same. > (Remember inheritance m,eans you are imp0lementing > an "is a" relationship. So FTPFiles is an FTP...or > should be.) I was struggling to come up with a good name here that would not cause me any name collision issues with the contents of ftplib.FTP(). I have for the moment changed the class name to "CustomFTP", which bothers me for some reason that I cannot put my finger on. However, this looks to become a non-issue; see below. >> 4) As this class stuff is mostly treading new ground for me, am I >> doing anything that I should not be doing or should do in a more >> preferred way? Keep in mind that I am just starting on this code >> today. > > I'll leave someone with more ftplib experience to answer the other > points but the question I'd ask is what are you planning to add to FTP? > Creating a new class by inheritance implies that you are going to be > extending (or specializing) its capabilities in some way. What are you > planning to extend/specialize? For example are you going to limit it to > manipulating files only? ie prevent listing directories say? My first objective was just to play around with inheritance as a learning opportunity. Now that I have gotten it to work and have somewhat a feel for the possibilities, I am actually going to abandon it for this specific project. I think I can use the FTP class unmodified and just write appropriate helper functions to get the specifics of what I want, passing my specific FTP instance object to these functions. > You need to know what you are changing to warrant using inheritance. > Inheritance is a powerful tool but it carries lots of potential for > problems too, especially if you plan on mixing your new class in with > the old one (or sharing it with others who will) - you need to be > careful to abide by the Liskov substitution principle (LSP). I looked up LSP last night. I can see how I can easily get burned even on something seemingly simple. One example, which I imagine is often used, is of a square class inheriting from a rectangle class. Squares have same sized sides; rectangles not necessarily so. So any size changing methods from the rectangle class inherited by the square class can potentially wreak havoc on squares. Am I getting the essence of the potential issues I might encounter? boB ___ Tutor maillist - Tutor@python.org To unsubscribe or change subscription options: https://mail.python.org/mailman/listinfo/tutor
Re: [Tutor] Py 2.4.4: Inheriting from ftplib.FTP()
I guess I did not emphasize enough that I was just starting to think through this. The code I posted yesterday was more in the way of exploratory code, trying to understand how to implement inheritance, using new-style classes (I am trying to integrate the work with Python 3 at home as much as possible with what I am forced to in Python 2.4 at work where I have no choices as to Python version.). On Fri, Jun 17, 2016 at 10:31 AM, Steven D'Aprano wrote: > Some futher thoughts: > > On Thu, Jun 16, 2016 at 10:38:13AM -0500, boB Stepp wrote: >> class FTPFiles(FTP, object): >> """FTP files to Windows server location(s).""" >> >> def __init__(self, host=server_ip, user=user, passwd=passwd): >> """Initialize FTPFiles object. Normally the defaults will be >> used.""" >> >> super(FTPFiles, self).__init__(host, user, passwd) >> self.host = host >> self.user = user >> self.passwd = passwd > > Do you actually need to record these? Once they're used to establish a > connection and login, what are they for? No, I was just spelling everything out for myself while I was trying to figure out why my original code was not working. All the things I said I "learned" were not in my earlier versions. These lines have already been excised as I am getting closer to something I might actually want to implement. Also, now that I have had the opportunity to play around with inheritance, I don't see any need to specialize the FTP class as I mention in my response to Alan I just sent out. > >> def print_welcome_msg(self): >> """Print welcome message sent by FTP server.""" >> print self.getwelcome() > > The getwelcome method already prints the message, which is a bad design. > But only if debugging is true. So I would approach this in one of two > ways: The only point of this method was to ensure that I was actually connected to my server. During earlier versions, things were acting weird and I was not understanding what was going on. So I wanted to be certain I was in fact connected; it turned out I was not! This also has been excised today. > (1) Delegate to the existing getwelcome method: > > def print_welcome_msg(self): > save_flag = self.debugging > self.debugging = True > try: > x = self.getwelcome() # prints the msg > finally: > self.debugging = save_flag > > > (2) Re-implement the print functionality. > > def print_welcome_msg(self): > print "*welcome*", self.welcome > > > (3) If you really want to be paranoid, use: > > print "*welcome*", self.sanitize(self.welcome) > > > although I don't think it's likely to make any real difference in > practice. > > (The sanitize method makes a feeble attempt to hide the password.) Some interesting ideas to aid debugging. Thanks! >> What I learned today: >> >> 1) FTP from ftplib appears to be an old-style class. >> >> 2) I can't just use "class FTPFiles(FTP)" or I will be using old-style >> classes. > > Is this a problem? Old-style classes are good enough for many purposes. Not really. I am just trying to consolidate the studies I am doing at home with Python 3 as much as I can when I am working with Python 2. >> 3) I need to use "class FTPFiles(FTP, object)" to use new-style >> classes and "object" must come AFTER "FTP". >> >> 4) I have to use "super(FTPFiles, self).__init__(host, user, passwd)" >> or I cannot successfully inherit from the FTP() class. Also, "self" >> apparently must come AFTER "FTPFiles" in the super expression. > > For old-style classes, don't use super because it doesn't work. Instead > just write: > > FTP.__init__(self, host, user, passwd) Yeah, if I just stuck to old-style, things would have been easier. > That means that you cannot engage in multiple inheritence with new-style > classes, but MI is a serious pain to get right, and 99% of the time it > is overkill, so you're not missing much. Right now just the simpler OOP stuff is a "serious pain" while I am still in the relatively early stages of learning. ~(:>)) boB ___ Tutor maillist - Tutor@python.org To unsubscribe or change subscription options: https://mail.python.org/mailman/listinfo/tutor
Re: [Tutor] Py 2.4.4: Inheriting from ftplib.FTP()
On 17/06/16 16:41, boB Stepp wrote: >> Inheritance is a powerful tool but it carries lots of potential for >> problems too,... > > I looked up LSP last night. I can see how I can easily get burned > even on something seemingly simple. One example, which I imagine is > often used, is of a square class inheriting from a rectangle class. > Squares have same sized sides; rectangles not necessarily so. So any > size changing methods from the rectangle class inherited by the square > class can potentially wreak havoc on squares. Am I getting the > essence of the potential issues I might encounter? Yes, that's one case. Another good example(in Java) is in the book "Effective Java". It uses the example of a superclass which is a collection and has add() and add_many() methods. Now let's say you want to create a counted collection so you override the add() method to add one to a total each time its called. Then you override add_many() to add the number of items in the params list. The problem is that, unknown to you, the inherited add_many() calls self.add() internally so you wind up double counting on add_many()... You need to know about the internals of the superclass to correctly implement your sub class, which breaks the concept of data hiding... There is no way round this its just one of the inherent(sic) issues with OOP, but a good reason to use delegation rather than inheritance if possible. Inheritance is a powerful tool but comes with sharp claws. (Its even worse in a static language like Java but even in Python there are plenty of opportunities to mess up). -- Alan G Author of the Learn to Program web site http://www.alan-g.me.uk/ http://www.amazon.com/author/alan_gauld Follow my photo-blog on Flickr at: http://www.flickr.com/photos/alangauldphotos ___ Tutor maillist - Tutor@python.org To unsubscribe or change subscription options: https://mail.python.org/mailman/listinfo/tutor
Re: [Tutor] Py 2.4.4: Inheriting from ftplib.FTP()
On Fri, Jun 17, 2016 at 11:42 AM boB Stepp wrote: > On Thu, Jun 16, 2016 at 11:40 AM, Alan Gauld via Tutor > wrote: > > On 16/06/16 16:38, boB Stepp wrote: > > > >> class FTPFiles(FTP, object): > >> """FTP files to Windows server location(s).""" > > I was struggling to come up with a good name here that would not cause > me any name collision issues with the contents of ftplib.FTP(). That's why we have namespaces. Your ``FTP`` would not collide with ``ftplib.FTP``, because they are in separate modules. I looked up LSP last night. I can see how I can easily get burned > even on something seemingly simple. One example, which I imagine is > often used, is of a square class inheriting from a rectangle class. > Squares have same sized sides; rectangles not necessarily so. So any > size changing methods from the rectangle class inherited by the square > class can potentially wreak havoc on squares. Am I getting the > essence of the potential issues I might encounter? > Yes, that's the gist of it. It's very hard to anticipate what features your base class may need in the future, months or years down the road. Many of them may be inappropriate for one or more child classes. ___ Tutor maillist - Tutor@python.org To unsubscribe or change subscription options: https://mail.python.org/mailman/listinfo/tutor
[Tutor] Best way to do FTP login?
I could do this: from ftplib import FTP ftp = FTP('ip_address', 'username', 'password') Or, I could do this: ftp = FTP('ip_address') ftp.login('username', 'password') Most of the examples I am seeing online use the second approach. Is there some reason why this is to be preferred? TIA! -- boB ___ Tutor maillist - Tutor@python.org To unsubscribe or change subscription options: https://mail.python.org/mailman/listinfo/tutor
[Tutor] help with comparing list of tuples in python 2
Hi there, My apologies if this is a trivial question but I am sort of new to python. Here is my problem: I have a list of dictionaries. Each dictionary has a word and its position in the text the positions are in the form of a tuple. Here is an example: [ {'position': (5, 4), 'term': u'happy',}, {'position': (5, 5), 'term': u'something'} ] for the potions, the first element is the paragraph number and the second is the word number in that paragraph(sequence from 1...n) What I would like to is find which words are next to each other. Meaning, they will be in the same paragraph and the difference of their word numbers is 1. Any help would be appreciated. Thank you ___ Tutor maillist - Tutor@python.org To unsubscribe or change subscription options: https://mail.python.org/mailman/listinfo/tutor
Re: [Tutor] Best way to do FTP login?
On Fri, Jun 17, 2016 at 12:46 PM boB Stepp wrote: > ftp = FTP('ip_address', 'username', 'password') > > Or > > ftp = FTP('ip_address') > ftp.login('username', 'password') > > Most of the examples I am seeing online use the second approach. Is > there some reason why this is to be preferred? Not that I can see. Perhaps only to show that the login method exists. I suggest using it in a context manager. py> with FTP('ftp.example.com', 'username', 'password') as ftp: ... ftp.dir() ___ Tutor maillist - Tutor@python.org To unsubscribe or change subscription options: https://mail.python.org/mailman/listinfo/tutor
Re: [Tutor] help with comparing list of tuples in python 2
On 17/06/16 20:18, Lulu J wrote: > I have a list of dictionaries. Each dictionary has a word and its position > in the text the positions are in the form of a tuple. > Here is an example: > [ > {'position': (5, 4), 'term': u'happy',}, > {'position': (5, 5), 'term': u'something'} > ] > > for the potions, the first element is the paragraph number and the second > is the word number in that paragraph(sequence from 1...n) > > What I would like to is find which words are next to each other. Meaning, > they will be in the same paragraph and the difference of their word numbers > is 1. You can sort them by providing a key function, for example, a simplified version:: >>> L = [{'k':1,'v':0},{'k':5,'v':9},{'k':2,'v':6},{'k':0,'v':12}] >>> sorted(L,key=lambda d: d['v']) [{'k': 1, 'v': 0}, {'k': 2, 'v': 6}, {'k': 5, 'v': 9}, {'k': 0, 'v': 12}] >>> sorted(L,key=lambda d: d['k']) [{'k': 0, 'v': 12}, {'k': 1, 'v': 0}, {'k': 2, 'v': 6}, {'k': 5, 'v': 9}] >>> Then filter your results to find an adjacent pair that have matching positions. (This may not be necessary if you have all of the words since they should naturally be placed adjacent to each other, but if you only have key words it will be needed) Something like (untested) neighbours = [item for index,item in enumerate(data) if item['position'][0] == data[index+1][position'][0] and item['position'][1] == data[index+1][position'][1]-1] But there are lots of possible gotchas here. - look out for the last item which will give you an index error! - what happens to words that appear more than once? Are they in your list more than once? - probably more :-( -- Alan G Author of the Learn to Program web site http://www.alan-g.me.uk/ http://www.amazon.com/author/alan_gauld Follow my photo-blog on Flickr at: http://www.flickr.com/photos/alangauldphotos ___ Tutor maillist - Tutor@python.org To unsubscribe or change subscription options: https://mail.python.org/mailman/listinfo/tutor
Re: [Tutor] Best way to do FTP login?
On 17Jun2016 19:07, Michael Selik wrote: On Fri, Jun 17, 2016 at 12:46 PM boB Stepp wrote: ftp = FTP('ip_address', 'username', 'password') Or ftp = FTP('ip_address') ftp.login('username', 'password') Most of the examples I am seeing online use the second approach. Is there some reason why this is to be preferred? Not that I can see. Perhaps only to show that the login method exists. I suggest using it in a context manager. py> with FTP('ftp.example.com', 'username', 'password') as ftp: ... ftp.dir() I would also recommend looking at the netrc module. This parses the well known file .netrc for login and password, avoiding putting it in your code. You can put clauses for multiple machine in the .netrc, which lets your code work against multiple machines without changes. Note that the .netrc file still keeps the login and password in the clear, but if you lock the permissions down on your .netrc so that only you can read it there is a degree of security. Cheers, Cameron Simpson ___ Tutor maillist - Tutor@python.org To unsubscribe or change subscription options: https://mail.python.org/mailman/listinfo/tutor