[Tutor] Deleting items from a shelve file when items are unknown
Cameron Simpson
cs at cskk.id.au
Sat Oct 19 18:09:31 EDT 2019
On 18Oct2019 23:03, James Austin <james.londonsw15 at gmail.com> wrote:
>I am quite new to Python, so please bare with me.
I'd rather remain clothed, but I'm happy to bear with you.
>I am developing a basic clipboard application that saves text to a
>keyword and lists the saved items for the user. Users will then be
>able to paste saved text into an external application by using the
>keyword they first assigned. Saved data is stored in a Shelve file.
I _presume_ you mean Shelf objects from the "shelve" module? Please
verify that.
>I have a working prototype for the 'save' and 'list' features of the
>program. Currently this program is command line only.
Command line programmes are easy to use with scripts and easier to debug
than GUIs. Always a good starting point.
>Before adding the 'paste' feature, I am working on implementing a way
>for users to delete keywords and text they no longer want. This is
>where I hope the list can advise please. I am trying to write code
>that will allow the user to delete **any** keyword that they find in
>the list. A portion of my code is below and below that is a brief
>summary of what I have tried so far:
>
>---snip---
># Delete keywords/comments
>elif len(sys.argv) == 2 and sys.argv[1] == 'delete':
> if clipboardShelf[sys.argv[2]] in clipboardShelf.keys():
> clipboardShelf.pop()
Problem 1: if you have sys.argv[2], then len(sys.argv) is at least 3
(elements 0,1,2).
Personally I tend to pop things off sys.argv progressively so that they
can get nice names:
cmd = sys.argv.pop(0) # command name
op = sys.argv.pop(0) # operation
if op == 'delete':
key = sys.argv.pop(0)
This has the advantage of not hardwiring argument positions into your
code. (Suppose you latter add some option parsing ahead of the 'delete'
operation word?) It also mades the code more readable ("key" instead of
"sys.argv[2]").
Anyway, to the code again:
> if clipboardShelf[sys.argv[2]] in clipboardShelf.keys():
> clipboardShelf.pop()
A Shelf is a mutable mapping of keys to values. So
clipboardShelf[sys.argv[2]] is a clipboard value. That will not be in
the keys. You probably mean:
if sys.argv[2] in clipboardShelf.keys():
Then you go: clipboardShelf.pop(). I imagine your intent here it to
remove the clipboard entry with key sys.argv[2], but you do not tell the
pop method what key to remove. If clipboardShelf really is a mapping you
can go:
del clipboardShelf[sys.argv[2]]
>This code does not throw errors when tested with: python clipboard.py.
If you attached clipboard.py, it is gone. This list is text only and
discards attachments. Just paste the code into the message body. If the
cde is long, paste it at the end with your discussion up front.
>However, when I run python clipboard.py list, the keyword remains in
>the shelve file.
>
>Although my understanding is limited, I believe, from what I have
>read, that shelve files act like dictionaries. However, using the
>'del' option yields the same result.
Maybe there's some method to _save_ the new state of the clipboard?
I see that a shelve.Shelf object has .sync and /close methods. You need
to use there is the Shelf is to be saved back to the file.
>I have tried several variations including the following 'for' loop:
>---snip---
>elif len(sys.argv) == 2 and sys.argv[1] == 'delete':
> for key in clipboardShelf.keys():
> del clipboardShelf['']
This deletes the key '' many times, not the key specified by "key".
Also, if is not safe to modify a mapping while you are iterating over
it. This is a general rule, but in this specific case .keys() usually
returns a generator which yields keys. If you modify the mapping while
using that generator it may skip some keys or behave in other unexpected
ways. try:
keys = list(clipboardShelf.keys())
for key in keys:
del clipboardShelf[key]
i.e. run the generator completely and get a list, and _then_ modify the
mapping.
>I have also tried signifying the unknown key with empty brackets.
Is deleting an unknown key a sensible concept?
I see the Shelf class is a context manager. You chould wrap your command
line parse code in a with statement:
cmd = sys.argv.pop(0)
with shelve.open(filename, writeback=True) as clipboardShelf:
do delete, etc etc
When you exit the with suite the shelf gets saved.
Cheers,
Cameron Simpson <cs at cskk.id.au>
More information about the Tutor
mailing list