Re: [Tutor] Recommendation For A Complete Noob

2014-02-11 Thread Bob Williams
-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

2014-02-12 Thread Bob Williams
-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

2014-02-24 Thread Bob Williams
-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

2014-02-24 Thread Bob Williams
-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

2014-02-24 Thread Bob Williams
-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

2014-02-26 Thread Bob Williams
-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

2014-02-26 Thread Bob Williams
-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

2014-02-26 Thread Bob Williams
-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

2014-02-26 Thread Bob Williams
-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

2014-03-28 Thread Bob Williams
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?

2014-05-02 Thread Bob Williams
-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?

2014-05-03 Thread Bob Williams
-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

2014-06-11 Thread Bob Williams
-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

2014-06-30 Thread Bob Williams
-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

2014-07-08 Thread Bob Williams
-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

2014-07-08 Thread Bob Williams
-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?

2015-02-05 Thread Bob Williams
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?

2015-02-05 Thread Bob Williams
-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?

2015-02-05 Thread Bob Williams
-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?

2015-02-06 Thread Bob Williams
-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