Re: [Tutor] Recommendation For A Complete Noob
-BEGIN PGP SIGNED MESSAGE- Hash: SHA1 On 09/02/14 22:37, Altrius wrote: > Hi, > > I’m completely new to programming in general and everything I have > read so far has pointed me to Python. I’ll put this another way: > All I know is that a programming language is a medium for a human > to tell a computer what to do. After that I’m kinda lost. I was > just hoping to get some input as to where I might start. I’m not > completely computer illiterate but you can reply to me as if I am. > What should I work on learning first. I’m good at doing my own > research and teaching myself but I need to know what I’m > researching and where to start. Any advice would be VERY much > appreciated. > > Thanks, Altrius > Hi Altrius, I'm also a noob. In addition to all the excellent recommendations already posted, I would suggest setting yourself a task to solve in python. It's far more interesting than working through the examples in most books - the challenge is solving each problem as you come across them. Google is excellent. The task I set myself is to write a script that interrogates the rsyncd.log file every day, to tell me if any new music has been added to my collection by my son. My linux machine is on 24/7. I have had to work out how to open the file, how to tell if it's been altered in the last 24 hours, if so how to extract the lines of interest, and how to slice those lines to get the artist and album names into a list. So far, so good but my output contains duplicates, so my final task is to work out how to get rid of them. You may find me popping up here again in a few days ;-) Good luck. Bob - -- Bob Williams System: Linux 3.11.10-7-desktop Distro: openSUSE 13.1 (x86_64) with KDE Development Platform: 4.12.2 Uptime: 18:00pm up 1 day 22:01, 5 users, load average: 0.17, 0.17, 0.21 -BEGIN PGP SIGNATURE- Version: GnuPG v2.0.22 (GNU/Linux) Comment: Using GnuPG with Thunderbird - http://www.enigmail.net/ iEYEARECAAYFAlL6sVAACgkQ0Sr7eZJrmU54NgCeP+v3YJk7LxFBkYraOGUL3p94 h8YAn22UWIHzfnIutkk1yUNeMcPtfkgg =7Jq8 -END PGP SIGNATURE- ___ Tutor maillist - Tutor@python.org To unsubscribe or change subscription options: https://mail.python.org/mailman/listinfo/tutor
Re: [Tutor] Recommendation For A Complete Noob
-BEGIN PGP SIGNED MESSAGE- Hash: SHA1 On 12/02/14 00:58, Dave Angel wrote: > Bob Williams Wrote in message: > > >> to slice those lines to get the artist and album names into a >> list. >> >> So far, so good but my output contains duplicates, so my final >> task is to work out how to get rid of them. >> > > > Hint: a set will contain only one of each item. So if you have a > list of immutable items, the following will eliminate duplicates: > > newlist = list (set (oldlist)) > > Sometimes a dict is better, if only part of each item is to be > made unique. > > This assumes that order doesn't matter. If it does, perhaps an > ordered dict. > Many thanks, Dave. That worked perfectly. Ordering doesn't matter in this case, but I might try it as an exercise. Bob - -- Bob Williams System: Linux 3.11.10-7-desktop Distro: openSUSE 13.1 (x86_64) with KDE Development Platform: 4.12.2 Uptime: 06:00am up 2 days 10:01, 5 users, load average: 0.35, 0.31, 0.21 -BEGIN PGP SIGNATURE- Version: GnuPG v2.0.22 (GNU/Linux) Comment: Using GnuPG with Thunderbird - http://www.enigmail.net/ iEYEARECAAYFAlL7QxsACgkQ0Sr7eZJrmU6I+gCffgK34BBSBPQ02ZjAKm/TwlUQ VyoAn1etNjuywwWIa1e2fqx9YlGeXGu9 =NhPX -END PGP SIGNATURE- ___ Tutor maillist - Tutor@python.org To unsubscribe or change subscription options: https://mail.python.org/mailman/listinfo/tutor
[Tutor] os.symlink can't find target
-BEGIN PGP SIGNED MESSAGE- Hash: SHA1 My operating system is Linux (openSUSE 13.1). I'm trying to create symlinks. The following code: if pathList[j][-3:] == "mp3": linkName1 = pathList[j][0:-3] + "mp3" linkName2 = destPath + linkName1[len(sourcePath):] print 'Creating link %s -> %s' % (linkName2, pathList[j]) os.symlink(pathList[j], linkName2) fails with this error: Creating link /pollux/music/portable/testing/artists/Death in June/1995 Rose Clouds Of Holocaust/10 Lifebooks.mp3 -> /home/bob/music/artists/Death in June/1995 Rose Clouds Of Holocaust/10 Lifebooks.mp3 Traceback (most recent call last): File "/home/bob/Documents/scripts/python/flac2mp3.py", line 101, in os.symlink(pathList[j], linkName2) OSError: [Errno 2] No such file or directory The same thing happens in ipython, when I type the paths in manually. I have tried escaping the spaces with '\', but the same error is generated. The file "/home/bob/music/artists/Death in June/1995 Rose Clouds Of Holocaust/10 Lifebooks.mp3" definitely exists. Thanks, Bob - -- Bob Williams System: Linux 3.11.10-7-desktop Distro: openSUSE 13.1 (x86_64) with KDE Development Platform: 4.12.2 Uptime: 12:00pm up 11 days 20:00, 5 users, load average: 0.14, 0.17, 0.22 -BEGIN PGP SIGNATURE- Version: GnuPG v2.0.22 (GNU/Linux) Comment: Using GnuPG with Thunderbird - http://www.enigmail.net/ iEYEARECAAYFAlMLblkACgkQ0Sr7eZJrmU4qfACdGc7/U8dN6I/NcyJsHA7ILzcV Ea4AoIHSbWLkg5eQ1Lo5rN7z0FTse+YM =+wrZ -END PGP SIGNATURE- ___ Tutor maillist - Tutor@python.org To unsubscribe or change subscription options: https://mail.python.org/mailman/listinfo/tutor
Re: [Tutor] os.symlink can't find target
-BEGIN PGP SIGNED MESSAGE- Hash: SHA1 On 24/02/14 16:36, Peter Otten wrote: > os.symlink(existing_file, symlink_to_create) > > fails with that error if the directory that shall contain the new > symlink does not exist. You can create it before making the symlink > with > Peter, Many thanks. I was fixating on the existing_file, not realising I had to create a home for the symlink first. > try: os.makedirs(os.path.dirname(symlink_to_create)) except OSError > as err: # Assume the directory exists. # A thorough coder would > check the errno here pass Regards Bob - -- Bob Williams System: Linux 3.11.10-7-desktop Distro: openSUSE 13.1 (x86_64) with KDE Development Platform: 4.12.2 Uptime: 12:00pm up 11 days 20:00, 5 users, load average: 0.14, 0.17, 0.22 -BEGIN PGP SIGNATURE- Version: GnuPG v2.0.22 (GNU/Linux) Comment: Using GnuPG with Thunderbird - http://www.enigmail.net/ iEYEARECAAYFAlMLe3QACgkQ0Sr7eZJrmU6QmQCeLUSIh0l97T017KrIHXT92Xhd YuQAn2To2AOXNpbA4fZ+4i6Swt4RdsMg =NgLw -END PGP SIGNATURE- ___ Tutor maillist - Tutor@python.org To unsubscribe or change subscription options: https://mail.python.org/mailman/listinfo/tutor
Re: [Tutor] os.symlink can't find target
-BEGIN PGP SIGNED MESSAGE- Hash: SHA1 On 24/02/14 16:56, Mark Lawrence wrote: > On 24/02/2014 16:36, Peter Otten wrote: >> Bob Williams wrote: >> [...] >>> Thanks, >> >> os.symlink(existing_file, symlink_to_create) >> >> fails with that error if the directory that shall contain the new >> symlink does not exist. You can create it before making the >> symlink with >> >> try: os.makedirs(os.path.dirname(symlink_to_create)) except >> OSError as err: # Assume the directory exists. # A thorough coder >> would check the errno here pass >> > > Python 3.3+ allows finer grained error handling than that shown > above, so you could catch FileExistsError, see > http://legacy.python.org/dev/peps/pep-3151/ for the details. > I'm using a module (mutagen) elsewhere in this script, which only works in Python 2 (so far). Also, I'm fairly new to this, so getting things working takes precedence over 'good practice' like error trapping. But I'm also aware that it's best to establish good habits early on. Bob - -- Bob Williams System: Linux 3.11.10-7-desktop Distro: openSUSE 13.1 (x86_64) with KDE Development Platform: 4.12.2 Uptime: 12:00pm up 11 days 20:00, 5 users, load average: 0.14, 0.17, 0.22 -BEGIN PGP SIGNATURE- Version: GnuPG v2.0.22 (GNU/Linux) Comment: Using GnuPG with Thunderbird - http://www.enigmail.net/ iEYEARECAAYFAlMLfOMACgkQ0Sr7eZJrmU4IgQCgn5MeqNsCOgiS3QY8g2jjMooR 65oAnjcWZaHrfe78C2WvHjMNlqZqjgo1 =CnnC -END PGP SIGNATURE- ___ Tutor maillist - Tutor@python.org To unsubscribe or change subscription options: https://mail.python.org/mailman/listinfo/tutor
Re: [Tutor] os.symlink can't find target
-BEGIN PGP SIGNED MESSAGE- Hash: SHA1 Hi Cameron, Many thanks for your helpful comments. I do still have some problems with my script, but it's probably better to start a new thread with an appropriate subject. I'm a bit new to Python, so it still seems like magic sometimes (someone else said the same in a different thread). A lot of my coding is 'trial & error', and I'll admit that at the moment my main goal is getting things to work; after that I can explore making my code more efficient/readable etc. But I appreciate your suggestions. On 26/02/14 05:31, Cameron Simpson wrote: > Hi Bob, > [...] > > The other things are just script remarks, not directly related to > your problem: > > On 24Feb2014 16:07, Bob Williams > wrote: >> if pathList[j][-3:] == "mp3": > > This is often written (I've inserted a dot, assuming you don't > want "foomp3", only "foo.mp3"): > > if pathList[j].endswith(".mp3"): > > More readable, and also more reliable because it doesn't rely on > you getting the "3" correct. > Yes, and reduces the need for explanatory comments. >> linkName1 = pathList[j][0:-3] + "mp3" > > Isn't this exactly the same as pathList[j] ? > Actually, no. pathList[j] can contain either .mp3 files or .flac files. In fact the main function of the script is to run all the flacs through lame to convert them into mp3s. If they are already mp3s, then a symlink will suffice. >> linkName2 = destPath + linkName1[len(sourcePath):] > > You might want to spell this: > > linkName2 = os.path.join(destPath, linkName1[len(sourcePath):]) > More good stuff. :-) Bob - -- Bob Williams System: Linux 3.11.10-7-desktop Distro: openSUSE 13.1 (x86_64) with KDE Development Platform: 4.12.2 Uptime: 12:00pm up 13 days 20:00, 6 users, load average: 0.10, 0.19, 0.26 -BEGIN PGP SIGNATURE- Version: GnuPG v2.0.22 (GNU/Linux) Comment: Using GnuPG with Thunderbird - http://www.enigmail.net/ iEYEARECAAYFAlMOC0UACgkQ0Sr7eZJrmU77fwCeIAgFpOKEdt5C6Q/qzHPQglnm 91gAnRLHLs5u/369RNsBOMOFeZVhTiN5 =w7La -END PGP SIGNATURE- ___ Tutor maillist - Tutor@python.org To unsubscribe or change subscription options: https://mail.python.org/mailman/listinfo/tutor
[Tutor] Editing values from a dictionary
-BEGIN PGP SIGNED MESSAGE- Hash: SHA1 Hi List, I have two problems, but it's possible that one solution will suffice. I am using a module called mutagen to extract audio metadata from .flac files. The output of mutagen is in the form of a dictionary, so In [1]: import mutagen.flac In [2]: metadata = mutagen.flac.Open("/home/bob/music/artists/The Incredible String Band/1967 The 5000 Spirits Or The Layers Of The Onion/08 The Hedgehog's Song.flac") In [3]: print metadata["artist"] [u'The Incredible String Band'] I now want to pass that string to another program, but I want to strip off the leading [u' and the trailing ']. However, this doesn't work: In [4]: artistName = metadata["artist"][3:-2] In [5]: print artistName [] I was expecting The Incredible String Band, not [] What am I doing wrong? Or what have I misunderstood? The other problem concerns the program that receives these arguments - it complains (and stops with an error) if one the arguments is empty. For example, the flac file may not have the date information: Traceback (most recent call last): File "/home/bob/Documents/scripts/python/flac2mp3v2.py", line 81, in subprocess.call(['lame', '--add-id3v2', '--ignore-tag-errors', '--tt', str(metadata['title']), '--ta', str(metadata['artist']), '--tl', str(metadata['album']), '--ty', str(metadata['date']), '--tn', str(metadata['tracknumber']), '--tg', str(metadata['genre']), tempName1, tempName3]) File "/usr/lib/python2.7/site-packages/mutagen/__init__.py", line 85, in __getitem__ else: return self.tags[key] File "/usr/lib/python2.7/site-packages/mutagen/_vorbis.py", line 184, in __getitem__ if not values: raise KeyError, key KeyError: 'date' If it's possible to edit the string value that gets passed to subprocess.call('lame'...) - see problem #1 above, would it also be possible to define a default value if the original field is empty? Bob - -- Bob Williams System: Linux 3.11.10-7-desktop Distro: openSUSE 13.1 (x86_64) with KDE Development Platform: 4.12.2 Uptime: 12:00pm up 13 days 20:00, 6 users, load average: 0.10, 0.19, 0.26 -BEGIN PGP SIGNATURE- Version: GnuPG v2.0.22 (GNU/Linux) Comment: Using GnuPG with Thunderbird - http://www.enigmail.net/ iEYEARECAAYFAlMOH9sACgkQ0Sr7eZJrmU5ufACeILRlmiXt4CgDa6ZpdTI3Npm5 FToAn2+AcjNKGxJKU+9nE9IdsoEqlQdd =JpdC -END PGP SIGNATURE- ___ Tutor maillist - Tutor@python.org To unsubscribe or change subscription options: https://mail.python.org/mailman/listinfo/tutor
Re: [Tutor] Editing values from a dictionary
-BEGIN PGP SIGNED MESSAGE- Hash: SHA1 On 26/02/14 17:29, Ben Finney wrote: > Bob Williams writes: > >> In [3]: print metadata["artist"] [u'The Incredible String Band'] >> >> I now want to pass that string to another program, but I want to >> strip off the leading [u' and the trailing ']. > > You may be assuming that ‘metadata["artist"]’ is a text string; I > suspect it is not. > > Try ‘type(metadata["artist"])’, to get Python to tell you what the > type of that object is. > Aha! Sounds of pennies dropping ;-) In [7]: type(metadata["artist"]) Out[7]: list In [12]: print metadata["artist"][0] The Incredible String Band Gets me what I want. Thank you. Bob - -- Bob Williams System: Linux 3.11.10-7-desktop Distro: openSUSE 13.1 (x86_64) with KDE Development Platform: 4.12.2 Uptime: 12:00pm up 13 days 20:00, 6 users, load average: 0.10, 0.19, 0.26 -BEGIN PGP SIGNATURE- Version: GnuPG v2.0.22 (GNU/Linux) Comment: Using GnuPG with Thunderbird - http://www.enigmail.net/ iEYEARECAAYFAlMOKP8ACgkQ0Sr7eZJrmU5a0ACdEH9kJPtHmbQ9w8YXrUc3NJT1 /t8AnitS+J4+kcM2z+Ai6Ak7cbe7Qnmk =Sv8P -END PGP SIGNATURE- ___ Tutor maillist - Tutor@python.org To unsubscribe or change subscription options: https://mail.python.org/mailman/listinfo/tutor
Re: [Tutor] os.symlink can't find target
-BEGIN PGP SIGNED MESSAGE- Hash: SHA1 On 26/02/14 15:41, Bob Williams wrote: On 26/02/14 05:31, Cameron Simpson wrote: >>> linkName1 = pathList[j][0:-3] + "mp3" >>> >>> Isn't this exactly the same as pathList[j] ? >>> > Actually, no. Actually, you are right. I've trimmed down that block now, thank you. Bob - -- Bob Williams System: Linux 3.11.10-7-desktop Distro: openSUSE 13.1 (x86_64) with KDE Development Platform: 4.12.2 Uptime: 18:00pm up 3:41, 5 users, load average: 2.73, 2.45, 1.92 -BEGIN PGP SIGNATURE- Version: GnuPG v2.0.22 (GNU/Linux) Comment: Using GnuPG with Thunderbird - http://www.enigmail.net/ iEYEARECAAYFAlMObU0ACgkQ0Sr7eZJrmU5AhgCgpolM3vDLEDzEy8t1o4O+5zCA B58AoJJC3IeyXqt3onBNnoaUaW833Lj3 =BhVn -END PGP SIGNATURE- ___ Tutor maillist - Tutor@python.org To unsubscribe or change subscription options: https://mail.python.org/mailman/listinfo/tutor
Re: [Tutor] Slices of lists of lists
On 28/03/14 09:42, Jose Amoreira wrote: > Hello! > Here is something that surprised me and I still didn't get it. > > If we want to store a matrix in pure python (no numpy), the first thing > that comes to (my) mind is to use a list of lists, like the list l below: > In [1]: l=[ >...:[11,12,13], >...:[21,22,23] >...: ] > > We can access individual components of this object in a simple, to be > expected way: > > In [2]: l[0][1], l[1][0] > Out[2]: (12, 21) > > OK, that's fine. If we want to access individual rows of this matrix > like object, the standard slice notation (on the second index) works as > expected also: > > In [3]: l[0][:] > Out[3]: [11, 12, 13] > > In [4]: l[1][:] > Out[4]: [21, 22, 23] > > Again, fine! But what if we want to access a particular row? My first > guess was that standard slice notation on the first index would do it, > but it doesn't! Instead, we get the rows again: > > In [6]: l[:][0] > Out[6]: [11, 12, 13] > > In [7]: l[:][1] > Out[7]: [21, 22, 23] > Jose, Just for clarity, are you trying to access a particular *column* in your last example? Bob -- Bob Williams System: Linux 3.11.10-7-desktop Distro: openSUSE 13.1 (x86_64) with KDE Development Platform: 4.12.3 Uptime: 06:00am up 4 days 19:51, 4 users, load average: 0.37, 0.18, 0.15 ___ Tutor maillist - Tutor@python.org To unsubscribe or change subscription options: https://mail.python.org/mailman/listinfo/tutor
[Tutor] Logical error?
-BEGIN PGP SIGNED MESSAGE- Hash: SHA1 Hi, I'm fairly new to coding and python. My system is linux (openSUSE 13.1). I've written the following code to examine a log file, and extract strings from certain lines if two conditions are met, namely that the file has been modified today, and the line contains the string 'recv'. - ---Code--- #!/usr/bin/python import sys import datetime import codecs import subprocess # Format date as /MM/DD today = (datetime.datetime.now()).strftime('%Y/%m/%d') fullPath = [] # declare (initially empty) lists truncPath = [] with codecs.open('/var/log/rsyncd.log', 'r') as rsyncd_log: for line in rsyncd_log.readlines(): fullPath += [line.decode('utf-8', 'ignore').strip()] if fullPath[-1][0:10] == today: print("\n Rsyncd.log has been modified in the last 24 hours...") else: print("\n No recent rsync activity. Nothing to do.\n") sys.exit() # Search for lines starting with today's date and containing 'recv' # Strip everything up to and including 'recv' and following last '/' path separator for i in range(0, len(fullPath)): if fullPath[i][0:10] == today and 'recv' in fullPath[i]: print("got there") begin = fullPath[i].find('recv ') end = fullPath[i].rfind('/') fullPath[i] = fullPath[i][begin+5:end] truncPath.append(fullPath[i]) print(" ...and the following new albums have been added:\n") else: print(" ...but no new music has been downloaded.\n") sys.exit() - ---Code--- The file rsyncd.log typically contains lines such as (sorry about the wrapping): 2014/05/02 19:43:14 [20282] host109-145-nnn-xxx.range109-145.btcentralplus.com recv Logical Progression Level 3 (1998) Intense/17 Words 2 B Heard Collective - Sonic Weapon.flac 72912051 72946196 I would expect the script to output a list of artist and album names, eg Logical Progression Level 3 (1998) Intense. IOW what is between the string 'recv' and the trailing '/'. What it actually produces is: :~> python ~/bin/newstuff.py Rsyncd.log has been modified in the last 24 hours... ...but no new music has been downloaded. This suggests that the first 'if' clause (matching the first 10 characters of the last line) is satisfied, but the second one isn't, as the flow jumps to the second 'else' clause. As the script runs without complaint, this is presumably a logical error rather than a syntax error, but I cannot see where I've gone wrong. Bob - -- Bob Williams System: Linux 3.11.10-7-desktop Distro: openSUSE 13.1 (x86_64) with KDE Development Platform: 4.13.0 Uptime: 06:00am up 11:26, 4 users, load average: 0.00, 0.02, 0.05 -BEGIN PGP SIGNATURE- Version: GnuPG v2.0.22 (GNU/Linux) Comment: Using GnuPG with Thunderbird - http://www.enigmail.net/ iEYEARECAAYFAlNkGewACgkQ0Sr7eZJrmU57YwCgg91pxyQbFMSe+TqHkEjMuzQ6 03MAnRQ50up6v+kYE+Hf/jK6yOqQw4Ma =+w0s -END PGP SIGNATURE- ___ Tutor maillist - Tutor@python.org To unsubscribe or change subscription options: https://mail.python.org/mailman/listinfo/tutor
Re: [Tutor] Logical error?
-BEGIN PGP SIGNED MESSAGE- Hash: SHA1 Hi Steven, On 03/05/14 02:53, Steven D'Aprano wrote: > Hi Bob, and welcome! > > My responses interleaved with yours, below. > > On Fri, May 02, 2014 at 11:19:26PM +0100, Bob Williams wrote: >> -BEGIN PGP SIGNED MESSAGE- Hash: SHA1 >> >> Hi, >> >> I'm fairly new to coding and python. My system is linux >> (openSUSE 13.1). > > Nice to know. And I see you have even more infomation about your > system in your email signature, including your email client and > uptime. But what you don't tell us is what version of Python you're > using. I'm going to guess that it is something in the 3.x range, > since you call print as a function rather than a statement, but > can't be sure. > I have both 2 and 3 installed here, but I call this script with python2. I guess I should concentrate on Python 3 as that's the way things are going. > Fortunately in this case I don't think the exact version matters. > > > [...] >> fullPath = [] # declare (initially empty) lists truncPath = [] >> >> with codecs.open('/var/log/rsyncd.log', 'r') as rsyncd_log: for >> line in rsyncd_log.readlines(): fullPath += [line.decode('utf-8', >> 'ignore').strip()] > > A small note about performance here. If your log files are very > large (say, hundreds of thousands or millions of lines) you will > find that this part is *horribly horrible slow*. There's two > problems, a minor and a major one. > The log file is typically a few thousand lines, so my code runs fast enough, but I understand your point. > First, rsyncd_log.readlines will read the entire file in one go. > Since you end up essentially copying the whole file, you end up > with two large lists of lines. There are ways to solve that, and > process the lines lazily, one line at a time without needing to > store the whole file. But that's not the big problem. > > The big problem is this: > > fullPath += [line.decode('utf-8', 'ignore').strip()] > > which is an O(N**2) algorithm. Do you know that terminology? Very > briefly: O(1) means approximately constant time: tripling the size > of the input makes no difference to the processing time. O(N) means > linear time: tripling the input triples the processing time. > O(N**2) means quadratic time: tripling the input increases the > processing time not by a factor of three, but a factor of three > squared, or nine. > > With small files, and fast computers, you won't notice. But with > huge files and a slow computer, that could be painful. > > Instead, a better approach is: > > fullPath.append(line.decode('utf-8', 'ignore').strip()) > > which avoids the O(N**2) performance trap. > Understood. > [snip] > > Now at last we get to your immediate problem: the above is intended > to iterate over the lines of fullPath. But it starts at the > beginning of the file, which may not be today. The first time you > hit a line which is not today, the program exits, before it gets a > chance to advance to the more recent days. That probably means that > it looks at the first line in the log, determines that it is not > today, and exits. > I'd missed the (now obvious) point that my if condition contained two terms which both have to be true. > I'm going to suggest a more streamlined algorithm. Most of it is > actual Python code, assuming you're using Python 3. Only the > "process this line" part needs to be re-written. > > new_activity = False # Nothing has happened today. with > open('/var/log/rsyncd.log', 'r', encoding='utf-8', errors='ignore') > as rsyncd_log: for line in rsyncd_log: line = line.strip() if > line[0:10] == today and 'recv' in line: new_activity = True process > this line # <== fix this > > if not new_activity: print("no new albums have been added today") > Thanks. This works nicely. > > > This has the benefit that every line is touched only once, not > three times as in your version. Performance is linear, not > quadratic. You should be able to adapt this to your needs. > > Good luck, and feel free to ask questions! > - -- Bob Williams System: Linux 3.11.10-7-desktop Distro: openSUSE 13.1 (x86_64) with KDE Development Platform: 4.13.0 Uptime: 06:00am up 11:26, 4 users, load average: 0.00, 0.02, 0.05 -BEGIN PGP SIGNATURE- Version: GnuPG v2.0.22 (GNU/Linux) Comment: Using GnuPG with Thunderbird - http://www.enigmail.net/ iEYEARECAAYFAlNlXCYACgkQ0Sr7eZJrmU71OACfSy1XWSDA08DNAndcA89AZg6Z +2IAniQJIrSd7wVJWl2MEtEdHlcdkwfj =YtSq -END PGP SIGNATURE- ___ Tutor maillist - Tutor@python.org To unsubscribe or change subscription options: https://mail.python.org/mailman/listinfo/tutor
Re: [Tutor] code review
-BEGIN PGP SIGNED MESSAGE- Hash: SHA1 On 11/06/14 08:11, Alan Gauld wrote: > On 11/06/14 00:30, Adam Gold wrote: > >> Thanks for the reply Steven. It's no more than 100 lines at a >> guess > > In that case just copy and paste it into a message and send it to > the group. Anyone with time available can then take a peek. > > > hth One way noobs anywhere can learn is by listening in to other people's conversations - it's called lurking, I believe. So I would say, please do this on the list, and many more people than Adam may benefit. Others can ignore the thread if they wish. Bob - -- Bob Williams System: Linux 3.11.10-11-desktop Distro: openSUSE 13.1 (x86_64) with KDE Development Platform: 4.13.1 Uptime: 06:00am up 3 days 11:36, 3 users, load average: 0.05, 0.03, 0.05 -BEGIN PGP SIGNATURE- Version: GnuPG v2.0.22 (GNU/Linux) Comment: Using GnuPG with Thunderbird - http://www.enigmail.net/ iEYEARECAAYFAlOYFfkACgkQ0Sr7eZJrmU5EUwCgkvjIWEdp1AzodJj6j5fY5yAL wtsAoKFSwk2U4kq5HW5KsmeErH+9fcXI =lJCF -END PGP SIGNATURE- ___ Tutor maillist - Tutor@python.org To unsubscribe or change subscription options: https://mail.python.org/mailman/listinfo/tutor
Re: [Tutor] What are your favourite unofficial resources
-BEGIN PGP SIGNED MESSAGE- Hash: SHA1 On 29/06/14 23:41, Alan Gauld wrote: > I'm looking for tips for an appendix to a book that I'm working > on. > > What are the best unofficial (ie not python.org) resources for > people who have learned the basics but are not experts yet? ie > Typical tutor list "graduates"... > > I'm thinking about web sites, blogs, books, videos etc. Anything > that might be worth knowing about. > > I've got a few of my own - Activestate, O'Reilly, ByteOfPython, > PythonChallenge, ShowMeDo etc. > > But I thought the tutor list readers might be an interesting source > of alternatives that I hadn't thought of, or even heard of. > > All contributions considered :-) > Python Module of the Week <http://pymotw.com/2/> Bob - -- Bob Williams System: Linux 3.11.10-17-desktop Distro: openSUSE 13.1 (x86_64) with KDE Development Platform: 4.13.2 Uptime: 06:00am up 1 day 20:14, 0 users, load average: 0.04, 0.05, 0.05 -BEGIN PGP SIGNATURE- Version: GnuPG v2.0.22 (GNU/Linux) Comment: Using GnuPG with Thunderbird - http://www.enigmail.net/ iEYEARECAAYFAlOxRIsACgkQ0Sr7eZJrmU5kfQCgkE0dRzO1G+o/GX78s4U7oe3U mNQAoJ+ayTo+79Xj+9JaHoMrflxDHCzW =uWQJ -END PGP SIGNATURE- ___ Tutor maillist - Tutor@python.org To unsubscribe or change subscription options: https://mail.python.org/mailman/listinfo/tutor
[Tutor] subprocess.call not formatting date
-BEGIN PGP SIGNED MESSAGE- Hash: SHA1 I'm using Python 2.7.6 on an openSUSE linux system. I'm trying to convert a shell (bash) script to a python script, and everything's worked OK except this. The following line in the shell script btrfs subvolume snapshot /home/bob/A3/documents /home/bob/A3/docsnaps/`date +%y-%m-%d_%H-%M` creates a folder of the form /home/bob/A3/docsnaps/14-07-08_17-32 ie. the name is a formatted date string, which is what I want. In my python script, this subprocess.call('btrfs', 'subvolume', 'snapshot', '/home/bob/A3/documents', '/home/bob/A3/docsnaps/`date +%y-%m-%d_%H-%M`') creates a folder /home/bob/A3/docsnaps/`date +%y-%m-%d_%H-%M` In other words, it does not format the date, but takes the stuff between the backticks (`) as a string. I tried adding shell=True, but got the following error: Traceback (most recent call last): File "/home/bob/bin/btrfs-backup.py", line 55, in subprocess.call('btrfs', 'subvolume', 'snapshot', '/home/bob/A3/documents', '/home/bob/A3/docsnaps/`date +%y-%m-%d_%H-%M`', shell=True) File "/usr/lib64/python2.7/subprocess.py", line 522, in call return Popen(*popenargs, **kwargs).wait() File "/usr/lib64/python2.7/subprocess.py", line 658, in __init__ raise TypeError("bufsize must be an integer") TypeError: bufsize must be an integer Any suggestions, please? - -- Bob Williams System: Linux 3.11.10-17-desktop Distro: openSUSE 13.1 (x86_64) with KDE Development Platform: 4.13.2 Uptime: 06:00am up 2 days 9:43, 5 users, load average: 0.00, 0.02, 0.05 -BEGIN PGP SIGNATURE- Version: GnuPG v2.0.22 (GNU/Linux) Comment: Using GnuPG with Thunderbird - http://www.enigmail.net/ iEYEARECAAYFAlO8H9gACgkQ0Sr7eZJrmU7fdACgkBqVXT+Ozb+XqmEFwhPBdmeX NcgAnjY6YrbXcmUTAvgLPblk4rOWFAdH =vfIY -END PGP SIGNATURE- ___ Tutor maillist - Tutor@python.org To unsubscribe or change subscription options: https://mail.python.org/mailman/listinfo/tutor
Re: [Tutor] subprocess.call not formatting date
-BEGIN PGP SIGNED MESSAGE- Hash: SHA1 On 08/07/14 18:12, Peter Otten wrote: > I suggest that you calculate the folder name in Python instead: > > # untested name = > datetime.datetime.now().strftime("%y-%m-%d_%H-%M") destpath = > os.path.join("/home/bob/A3/docsnaps", name) subprocess.call( > ["btrfs", "subvolume", "snapshot", "/home/bob/A3/documents", > destpath]) Thank you. That worked perfectly. Once it's pointed out it is obvious to use the python solution, but my brain is becoming less agile as I collect more birthdays! Bob - -- Bob Williams System: Linux 3.11.10-17-desktop Distro: openSUSE 13.1 (x86_64) with KDE Development Platform: 4.13.2 Uptime: 06:00am up 2 days 9:43, 5 users, load average: 0.00, 0.02, 0.05 -BEGIN PGP SIGNATURE- Version: GnuPG v2.0.22 (GNU/Linux) Comment: Using GnuPG with Thunderbird - http://www.enigmail.net/ iEYEARECAAYFAlO8Nw8ACgkQ0Sr7eZJrmU6HVwCaAkT+nqxn818s1Di8mgqc9U1a qksAni7exn27xTGgDV2O6vSNtg8FbgMK =9I7G -END PGP SIGNATURE- ___ Tutor maillist - Tutor@python.org To unsubscribe or change subscription options: https://mail.python.org/mailman/listinfo/tutor
[Tutor] Nested for loops, possibly?
t;, sep='') do_sync(music_srcpath, music_syncpath) create_snaps(music_syncpath, music_snappath) print("Music backup completed.") expire_snaps(music_snaplist, today, mus_retain) print("Backing up Web server\n") do_sync(www_srcpath, www_syncpath) create_snaps(www_syncpath, www_snappath) print("Web server backup completed.") expire_snaps(www_snaplist, today, web_retain) print("Backing up Download repository\n") do_sync(repo_srcpath, repo_syncpath) create_snaps(repo_syncpath, repo_snappath) print("Download repository backup completed.") expire_snaps(repo_snaplist, today, rep_retain) print("\nAll backups completed.") print("\nUnmounting backup drive.\n") subprocess.call(['umount', mnt_path]) print("\n>>> Please power down the Quad external drive enclosure <<<\n") if __name__ == "__main__": main() **/Code** I would like to reduce all those repeated calls to do_sync() in main(), for example, to one by putting the *_srcpath and *_*syncpath variables into lists (eg. source_list and sync_list) and using a for loop to get the first item out of each list, then the second item, etc. Something like: for i in range(0, len(source_list)): for j in range(0, len(sync_list)): do_sync(source_list[i], sync_list[j]) but this will get all the values of sync_list[j] for each value of source_list[i], which is not what I want. I hope this is clear enough to see my problem? I realise that the print statements will need some work, I'm just trying to get the functionality working. TIA Bob -- Bob Williams System: Linux 3.16.7-7-desktop Distro: openSUSE 13.2 (x86_64) with KDE Development Platform: 4.14.3 Uptime: 06:00am up 7:55, 3 users, load average: 0.16, 0.05, 0.06 ___ Tutor maillist - Tutor@python.org To unsubscribe or change subscription options: https://mail.python.org/mailman/listinfo/tutor
Re: [Tutor] Nested for loops, possibly?
-BEGIN PGP SIGNED MESSAGE- Hash: SHA1 On 05/02/15 13:57, Mark Lawrence wrote: > On 05/02/2015 13:27, Bob Williams wrote: > >> >> I would like to reduce all those repeated calls to do_sync() in >> main(), for example, to one by putting the *_srcpath and >> *_*syncpath variables into lists (eg. source_list and sync_list) >> and using a for loop to get the first item out of each list, then >> the second item, etc. Something like: >> >> for i in range(0, len(source_list)): for j in range(0, >> len(sync_list)): do_sync(source_list[i], sync_list[j]) >> >> but this will get all the values of sync_list[j] for each value >> of source_list[i], which is not what I want. >> >> I hope this is clear enough to see my problem? I realise that >> the print statements will need some work, I'm just trying to get >> the functionality working. >> >> TIA >> >> Bob >> > > Apologies for shouting but this has been said several times in the > past so I'm deliberately emphasising the point. YOU *DON'T* NEED > TO LOOP THROUGH ITEMS IN A LIST USING range AND len. Hence:- > Sometimes you have to shout, if the class won't listen ;-) > for source in source_list: for sync in sync_list: do_sync(source, > sync) > Point taken, and understood. > Having said that I haven't looked at your code in depth, but I > think you're looking for something like:- > > for source, sync in zip(source_list, sync_list): do_sync(source, > sync) > > Let's try it. > >>>> def do_sync(source, sync): > ... print('Source is', source, 'Sync is', sync) ... >>>> source_list = ['a', 'b', 'c'] sync_list = ['w', 'x', 'y'] for >>>> source, sync in zip(source_list, sync_list): > ... do_sync(source, sync) ... Source is a Sync is w Source is b > Sync is x Source is c Sync is y > > Am I close? > Spot on! This is my first encounter with zip, but it does exactly what I want here. Many thanks Bob - -- Bob Williams System: Linux 3.16.7-7-desktop Distro: openSUSE 13.2 (x86_64) with KDE Development Platform: 4.14.3 Uptime: 06:00am up 7:55, 3 users, load average: 0.16, 0.05, 0.06 -BEGIN PGP SIGNATURE- Version: GnuPG v2 iEYEARECAAYFAlTTjYYACgkQ0Sr7eZJrmU4HlQCeKPfXiSJEiR5D1JqeZkPLAfRn AFMAoJhyCw75mC8b0+n8T6zIU0AnT0vM =8NMM -END PGP SIGNATURE- ___ Tutor maillist - Tutor@python.org To unsubscribe or change subscription options: https://mail.python.org/mailman/listinfo/tutor
Re: [Tutor] Nested for loops, possibly?
-BEGIN PGP SIGNED MESSAGE- Hash: SHA1 On 05/02/15 14:59, DaveA wrote: > > > On February 5, 2015 8:27:29 AM EST, Bob Williams > wrote: >> Hi, >> >> My script is running under Python 3.4.1 on a 64bit openSUSE >> linux system. It is a backup script making calls to rsync and >> btrfs-tools, and backing up several different paths. Here is the >> script, my question follows below: >> >> **Code** import datetime import glob import os, os.path import >> subprocess import sys >> >> if not os.getuid() == 0: print("\n*** This script must be run as >> root. ***\n") sys.exit() >> >> mnt_path = "/home/bob/A3" >> >> subprocess.call(["mount", "LABEL=backup", mnt_path]) if not >> os.path.ismount(mnt_path): print("\nBackup drive is not >> mounted\nCheck if it is attached.\n") sys.exit() else: >> print("\nBackup drive mounted at", mnt_path, "\n") >> >> src_path = "/home/bob" >> >> today = datetime.datetime.now() fname = >> today.strftime("%y-%m-%d_%H-%M") >> >> doc_retain = datetime.timedelta(days=90) pic_retain = >> datetime.timedelta(days=90) misc_retain = >> datetime.timedelta(days=90) etc_retain = >> datetime.timedelta(days=30) mus_retain = >> datetime.timedelta(days=30) web_retain = >> datetime.timedelta(days=30) rep_retain = >> datetime.timedelta(days=30) >> >> doc_srcpath = os.path.join(src_path, "Documents") pic_srcpath = >> os.path.join(src_path, "Pictures") misc_srcpath = src_path >> etc_srcpath = "/etc" music_srcpath = os.path.join(src_path, >> "music") www_srcpath = "/srv/www" repo_srcpath = >> os.path.join(src_path, "download") >> > Three things bother me about this portion of code, Too much code at > top-level, too many separate variables, too many global.The last > point doesn't matter much, since they're constant. > > I'd put these Values into a class, and make a list of instances. If > you're not yet comfortable with that, it would also be possible to > make a list per "paragraph", and use zip to combine them, as > already suggested. > I also felt that there was something wrong with that long list of variables. However, I'm new to classes, so I'll need to do some background reading. Thank you for the pointer. > The class would hold retain, srcpath, syncpath, snappath, etc. And > your list would have 7 instances of that class currently, > corresponding to your doc, pic, misc, ... > > That list would be THE global, replacing these 35 or so. It would > be populated something like: > > def initialize (worklist=[]): worklist . append (Job (90, > src_path, "Documents", "documents", "docsnaps") worklist .append > (Job (90, src_path, "Pictures", ... return worklist > > Now all the joins and globs are done in the Job initializer, just > once. > > .th.join(mnt_path, "documents") >> pic_syncpath = os.path.join(mnt_path, "pictures") misc_syncpath = >> os.path.join(mnt_path, "miscellaneous") etc_syncpath = >> os.path.join(mnt_path, "etc") music_syncpath = >> os.path.join(mnt_path, "music") www_syncpath = >> os.path.join(mnt_path, "www") repo_syncpath = >> os.path.join(mnt_path, "repo") >> >> doc_snappath = os.path.join(mnt_path, "docsnaps", fname) >> pic_snappath = os.path.join(mnt_path, "picsnaps", fname) >> misc_snappath = os.path.join(mnt_path, "miscsnaps", fname) >> etc_snappath = os.path.join(mnt_path, "etcsnaps", fname) >> music_snappath = os.path.join(mnt_path, "musicsnaps", fname) >> www_snappath = os.path.join(mnt_path, "wwwsnaps", fname) >> repo_snappath = os.path.join(mnt_path, "reposnaps", fname) >> >> doc_snaplist = glob.glob(mnt_path + "/docsnaps/*") pic_snaplist = >> glob.glob(mnt_path + "/picsnaps/*") misc_snaplist = >> glob.glob(mnt_path + "/miscsnaps/*") etc_snaplist = >> glob.glob(mnt_path + "/etcsnaps/*") music_snaplist = >> glob.glob(mnt_path + "/musicsnaps/*") www_snaplist = >> glob.glob(mnt_path + "/wwwsnaps/*") repo_snaplist = >> glob.glob(mnt_path + "/reposnaps/*") >> >> def do_sync(source, dest): subprocess.call(['rsync', '-av', >> '--safe-links', '--delete-excluded', '-F', source, dest]) >> p
Re: [Tutor] Nested for loops, possibly?
-BEGIN PGP SIGNED MESSAGE- Hash: SHA1 On 05/02/15 18:46, DaveA wrote: > You don't need much class understanding at all for this. Something > like: > > class Job: def __init__(self, retain, srcpath, suffix, syncpath, > snappath, ...): self.retain = retain = datetime.timedelta (days = > retain) self.srcpath = os.path.join (srcpath, suffix) self.syncpath > = os.path.join ( > > Notice that in the above method, the object is called self, while > in the loop in main it'll be called job, or whatever you use as a > loop variable. > >>> >>>>> The class would hold retain, srcpath, syncpath, snappath, >>>>> etc. And your list would have 7 instances of that class >>>>> currently, corresponding to your doc, pic, misc, ... >>>>> >>>>> That list would be THE global, replacing these 35 or so. It >>>>> would be populated something like: >>>>> >>>>> def initialize (worklist=[]): worklist . append (Job (90, >>>>> src_path, "Documents", "documents", "docsnaps") worklist >>>>> .append (Job (90, src_path, "Pictures", ... return >>>>> worklist > (Reformatting ) > > def initialize (worklist=[]): worklist . append (Job (90, > src_path, "Documents", "documents", "docsnaps") worklist > .append(Job (90, src_path, "Pictures", ... return worklist > >>>>> >>>>> Now all the joins and globs are done in the Job >>>>> initializer, just once. >>>>> > > >>>>>>> >>>>>>> def main(): print("Backing up ", src_path, >>>>>>> "/Documents\n", sep='') do_sync(doc_srcpath, >>>>>>> doc_syncpath) create_snaps(doc_syncpath, doc_snappath) >>>>>>> print("Documents backup completed.") >>>>>>> expire_snaps(doc_snaplist, today, doc_retain) >>>>> >>>>> At this point main becomes something like >>>>> > def main (): jobs = initialize () for job in jobs: do_sync > (job.srcpath, job.syncpath) create_snaps (job.syncpath, > job.snappath) expire_snaps (job.snaplist, ... > Thanks, that formatted nicely, and is a nice clear explanation. Bob - -- Bob Williams System: Linux 3.16.7-7-desktop Distro: openSUSE 13.2 (x86_64) with KDE Development Platform: 4.14.3 Uptime: 06:00am up 7:55, 3 users, load average: 0.16, 0.05, 0.06 -BEGIN PGP SIGNATURE- Version: GnuPG v2 iEYEARECAAYFAlTUiIIACgkQ0Sr7eZJrmU6arwCfXABX41NotsGViaEuozzqRJG1 UUUAmwd8zbZO1uOQuCTSoyDxt/kTx/yB =RkjX -END PGP SIGNATURE- ___ Tutor maillist - Tutor@python.org To unsubscribe or change subscription options: https://mail.python.org/mailman/listinfo/tutor