Passing varibles to another function with a button

I have a widget that list filenames
but doesn’t yet replace out commas in the naming.

I’m having a hard time understanding
how to pass variables between functions.

Basically I need:

[filename.rename(f, f.replace(’,’,
‘’)) for f in filename(’.’) if not f.startswith(’.’)]

to execute when I click the button.

Any help would be grateful.

import os
import sys
import wx
import re

class MainFrame(wx.Frame):
def init(self):
args = sys.argv[1:]
wx.Frame.init(self,None,wx.ID_ANY,title=‘List and Correct Naming of Files’,size=(600, 450))

    self.hbox2 = wx.BoxSizer()
    self.vbox= wx.BoxSizer(wx.VERTICAL)       
    self.background = wx.Panel(self)        
   
    self.top2 = wx.TextCtrl(self.background,style=wx.PROCESS_ENTER)
    self.top2.Bind(wx.EVT_LEFT_UP,self.OnChooseRoot)       
   
    self.bottomview = wx.TextCtrl(self.background,style = wx.TE_MULTILINE|wx.TE_RICH)     
    self.butExport2 = wx.Button(self.background,wx.ID_ANY,label = 'auto rename')      
   
    self.hbox2.Add(self.top2,proportion = 1,border=0)
    self.hbox2.Add(self.butExport2,proportion = 0,border=0)
   
    self.vbox.Add(self.hbox2,proportion = 0,flag = wx.EXPAND,border=0)       
    self.vbox.Add(self.bottomview,proportion = 1,flag = wx.EXPAND,border=0)
    self.Bind(wx.EVT_BUTTON, self.checkBtnClick2, self.butExport2)       

    self.background.SetSizer(self.vbox)
    self.Show()
    font1 = wx.Font(10, wx.SWISS, wx.ITALIC, wx.LIGHT, False, u'Courier New')   

    font4 = wx.Font(10, wx.SWISS, wx.ITALIC, wx.LIGHT, False, u'Courier New')
    self.top2.SetFont(font4)
    self.top2.SetForegroundColour((140,140,140))                   
    self.top2.SetValue("application feedback interruptor")

def OnChooseRoot(self, event):       
    dlg = wx.DirDialog(self, "Choose a directory:", style=wx.DD_DEFAULT_STYLE)
    if dlg.ShowModal() == wx.ID_OK:                       
        for dirname, dirnames, filenames in os.walk(dlg.GetPath()):               
            for filename in filenames:
                if ',' in filename:
                    font4 = wx.Font(8, wx.SWISS, wx.ITALIC, wx.LIGHT, False, u'Courier New')
                    self.top2.SetFont(font4)
                    self.top2.SetForegroundColour((250,100,100))                          
                    self.top2.SetValue("errors detected in naming")
                    font2 = wx.Font(8, wx.SWISS, wx.NORMAL, wx.NORMAL, False, u'Courier New')
                    self.bottomview.SetFont(font2)
                    s=('\n')                   
                    bs=(os.path.join(filename,s))
                    bf = (bs.replace("\\",""))
                    self.bottomview.AppendText(bf)
                dlg.Destroy()
               
def checkBtnClick2(filename, filenames):
    print filename

            [filename.rename(f, f.replace(',', '')) for f in filename('.') if not f.startswith('.')]   ## not callable

    for filename in filenames: ## not iterable
        filename.replace(",", "")

Hi George,

I attached a modified version of your code.

Some comments questions:
- your dlg.Destroy was called on each iteration, replaced it with "with" (see Python doc). This only works with recent Python 2.5+? and recent wxPython 2.8.11.
- Do you need a second button for the replace or do you just want to call it from your first button handler?
- if you want a second button for it then your handler signature has to be corrected - see def checkBtnClick2
- if you just want to call it then see "doReplace" and "doReplaceAlt"

Hope this helps, if not fire away with questions.

Werner

replaceSample.py (3.03 KB)

Although Werner’s code will explain it well by example, a really basic “lesson” about how to do what you want to do in the most general way:

#Create a button and bind it to an event handler:

self.myButton = wx.Button(self.MyPanel)

self.myButton.Bind(wx.EVT_BUTTON, self.OnMyButton() )

#Now in the handler for this button, call the function that does the work:

#I personally prefer not to put anything else in event handlers to keep the

#GUI code separate from the “internal processing” code.

def OnMyButton(self,event):

self.ProcessTheValueAndUpdateSomeOtherWidget()

#And now do the work itself:

def ProcessTheValueAndUpdateSomeOtherWidget(self,):

value_I_want_to_do_something_with = self.myTextCtrl.GetValue()

processed_value = value_I_want_to_do_something_with.split()

#update a widget with the new value

self.myOtherTextCtrl.SetValue(processed_value)

Also, for your questions to this list, if you want to include code that you have a question about, it is generally best to do it as a) an attachment (since formatting gets messed up if you just put it in the body of the email…I am flouting that advice above and I hope I got away with it this time), and b) as a small runnable sample (see this page: http://wiki.wxpython.org/MakingSampleApps)

A mistake on my part: That should have used .strip(), not .split()--if one
were to use split, you'd get a list, and you can't then set the value of
the other text control to a list. (But for the purpose of explaining your
issue, it really doesn't matter what you do with the value, it was just for
the purposes of an example of "manipulating" some values in your program)

···

On Thu, Aug 15, 2013 at 11:11 AM, C M <cmpython@gmail.com> wrote:

    processed_value = value_I_want_to_do_something_with.split()

I didn’t think you can pass varibles simply by using if statements on self.

···

On Thursday, August 15, 2013 10:26:17 AM UTC-5, Che M wrote:

On Thu, Aug 15, 2013 at 11:11 AM, C M cmpy...@gmail.com wrote:

processed_value = value_I_want_to_do_something_with.split()

A mistake on my part: That should have used .strip(), not .split()–if one were to use split, you’d get a list, and you can’t then set the value of the other text control to a list. (But for the purpose of explaining your issue, it really doesn’t matter what you do with the value, it was just for the purposes of an example of “manipulating” some values in your program)

I have a widget that list filenames
but doesn’t yet replace out commas in the naming.

I’m having a hard time understanding
how to pass variables between functions.

Basically I need:

[filename.rename(f, f.replace(‘,’,
‘’)) for f in filename(‘.’) if not f.startswith(‘.’)]

to execute when I click the button.

Any help would be grateful.

import os
import sys
import wx
import re

class MainFrame(wx.Frame):
def init(self):
args = sys.argv[1:]
wx.Frame.init(self,None,wx.ID_ANY,title=‘List and Correct Naming of Files’,size=(600, 450))

    self.hbox2 = wx.BoxSizer()
    self.vbox= wx.BoxSizer(wx.VERTICAL)       
    self.background = wx.Panel(self)        
   
    self.top2 = wx.TextCtrl(self.background,style=wx.PROCESS_ENTER)
    self.top2.Bind(wx.EVT_LEFT_UP,self.OnChooseRoot)       
   
    self.bottomview = wx.TextCtrl(self.background,style = wx.TE_MULTILINE|wx.TE_RICH)     
    self.butExport2 = wx.Button(self.background,wx.ID_ANY,label = 'auto rename')      
   
    self.hbox2.Add(self.top2,proportion = 1,border=0)
    self.hbox2.Add(self.butExport2,proportion = 0,border=0)
   
    self.vbox.Add(self.hbox2,proportion = 0,flag = wx.EXPAND,border=0)       
    self.vbox.Add(self.bottomview,proportion = 1,flag = wx.EXPAND,border=0)
    self.Bind(wx.EVT_BUTTON, self.checkBtnClick2, self.butExport2)       
    self.background.SetSizer(self.vbox)
    self.Show()
    font1 = wx.Font(10, wx.SWISS, wx.ITALIC, wx.LIGHT, False, u'Courier New')   
    font4 = wx.Font(10, wx.SWISS, wx.ITALIC, wx.LIGHT, False, u'Courier New')
    self.top2.SetFont(font4)
    self.top2.SetForegroundColour((140,140,140))                   
    self.top2.SetValue("application feedback interruptor")
def OnChooseRoot(self, event):       
    dlg = wx.DirDialog(self, "Choose a directory:", style=wx.DD_DEFAULT_STYLE)
    if dlg.ShowModal() == wx.ID_OK:                       
        for dirname, dirnames, filenames in os.walk(dlg.GetPath()):               
            for filename in filenames:
                if ',' in filename:
                    font4 = wx.Font(8, wx.SWISS, wx.ITALIC, wx.LIGHT, False, u'Courier New')
                    self.top2.SetFont(font4)
                    self.top2.SetForegroundColour((250,100,100))                          
                    self.top2.SetValue("errors detected in naming")
                    font2 = wx.Font(8, wx.SWISS, wx.NORMAL, wx.NORMAL, False, u'Courier New')
                    self.bottomview.SetFont(font2)
                    s=('\n')                   
                    bs=(os.path.join(filename,s))
                    bf = (bs.replace("\\",""))
                    self.bottomview.AppendText(bf)
                dlg.Destroy()
               
def checkBtnClick2(filename, filenames):
    print filename
            [filename.rename(f, f.replace(',', '')) for f in filename('.') if not f.startswith('.')]   ## not callable
    for filename in filenames: ## not iterable
        filename.replace(",", "")
···

On Thursday, August 15, 2013 8:49:11 AM UTC-5, George McCown wrote:

I added self.filename

I’m still unable to rename. My thinking is that you have to use rename and replace for filenames.

However I’m getting ‘unicode’ object has no attribute ‘rename’

What am I missing?

def checkBtnClick2(self, evt):
if self.filenames:
#print self.filenames
f = self.filename
for f in self.filenames:
if not f.startswith(‘.’):
#f.replace(“,”,“”) ## nothing
#f.rename(str(f, f.replace(“,”,“”)))

[filename.rename(f, f.replace(‘,’, ‘’)) for f in filename(‘.’) if not f.startswith(‘.’)] ## not callable

···

On Thursday, August 15, 2013 10:11:35 AM UTC-5, Che M wrote:

Although Werner’s code will explain it well by example, a really basic “lesson” about how to do what you want to do in the most general way:

#Create a button and bind it to an event handler:

self.myButton = wx.Button(self.MyPanel)

self.myButton.Bind(wx.EVT_BUTTON, self.OnMyButton() )

#Now in the handler for this button, call the function that does the work:

#I personally prefer not to put anything else in event handlers to keep the

#GUI code separate from the “internal processing” code.

def OnMyButton(self,event):

self.ProcessTheValueAndUpdateSomeOtherWidget()

#And now do the work itself:

def ProcessTheValueAndUpdateSomeOtherWidget(self,):

value_I_want_to_do_something_with = self.myTextCtrl.GetValue()

processed_value = value_I_want_to_do_something_with.split()

#update a widget with the new value

Also, for your questions to this list, if you want to include code that you have a question about, it is generally best to do it as a) an attachment (since formatting gets messed up if you just put it in the body of the email…I am flouting that advice above and I hope I got away with it this time), and b) as a small runnable sample (see this page: http://wiki.wxpython.org/MakingSampleApps)

self.myOtherTextCtrl.SetValue(processed_value)

George McCown wrote:

I added self.filename
I'm still unable to rename. My thinking is that you have to use
rename and replace for filenames.
However I'm getting 'unicode' object has no attribute 'rename'

"replace" is a string function. "os.rename" is a file system function.

    for f in self.filenames:
        if not f.startswith('.') and f.find(',') >= 0:
            os.rename( f, f.replace(',', '') )

Or, if you really want it as a comprehension:

    [os.rename(f, f.replace(',', '')) for f in self.filenames if not
f.startswith('.')]

···

--
Tim Roberts, timr@probo.com
Providenza & Boekelheide, Inc.

Hi George,

I added self.filename
I'm still unable to rename. My thinking is that you have to use rename and replace for filenames.
However I'm getting 'unicode' object has no attribute 'rename'
What am I missing?

Had to google a bit as I didn't know how to replace something within a list item within the original list.

x = ['la', 'lb.']

for idx, data in enumerate(x):
   x[idx] = data.replace('.', 'some')

x
['la', 'lbsome']

Werner

···

On 15/08/2013 20:03, George McCown wrote:

Hi George,

But then Tim beat me to it and gave you a better answer.

Werner

P.S.
This list comprehensions give me a head ache looking at them:-)

I don't understand this statement, given our discussion and given that I
didn't use any if statements. If you can elaborate, probably we can help
you understand this (important) point.

But generally in Python, you can pass an *object* to a function (in Python
you don't talk in terms of "variables" as much as "names" for objects)
simply by including it as one of the arguments when you call it. :

processed_list = self.ProcessTheList(self, my_list)

···

On Thu, Aug 15, 2013 at 1:57 PM, George McCown <georgemccown@gmail.com>wrote:

I didn't think you can pass varibles simply by using if statements on self.

I had to tell where my directory was in your code and tried:

def checkBtnClick2(self, evt):
if self.filenames:
folder = self.dirname
f = self.filename
for self.filenames in os.walk(folder):
for f in self.filenames:
if not f.startswith(‘.’) and f.find(‘,’) >= 0:
os.rename( f, f.replace(‘,’, ‘’) )

I get: ‘list’ object has no attribute ‘startswith’

I also tried:

if self.filenames:
print self.dirname
old = ‘,’
new = ‘’
folder = self.dirname
for self.filenames in os.walk(folder):
for self.filename in self.filenames:
if old in self.filename:
self.filename = os.path.join(self.filenames, self.filename)
print self.filename
os.rename(self.filename, self.filename.replace(old,new))

No error but no result.

Close but still no cigar for me.

···

On Thursday, August 15, 2013 1:08:39 PM UTC-5, Tim Roberts wrote:

George McCown wrote:

I added self.filename

I’m still unable to rename. My thinking is that you have to use

rename and replace for filenames.

However I’m getting ‘unicode’ object has no attribute ‘rename’

“replace” is a string function. “os.rename” is a file system function.

for f in self.filenames:

    if not f.startswith('.') and f.find(',') >= 0:

        os.rename( f, f.replace(',', '') )

Or, if you really want it as a comprehension:

[os.rename(f, f.replace(',', '')) for f in self.filenames if not

f.startswith(‘.’)]


Tim Roberts, ti...@probo.com

Providenza & Boekelheide, Inc.

this is pretty basic debugging, but a few hints:

you get that error because, well, a list object has no startswith()
method -- a string (or unicode) object does, so I suspect you are
accidentally calling it on the list of filenames, instead of the
filenames in that list.

use a debugger, or throw a few print statements in there so you can
see what your variables are when you try to use them.

we've gotten a bit out of wxPython territory here....

-Chris

···

On Thu, Aug 15, 2013 at 2:58 PM, George McCown <georgemccown@gmail.com> wrote:

I get: 'list' object has no attribute 'startswith'

--

Christopher Barker, Ph.D.
Oceanographer

Emergency Response Division
NOAA/NOS/OR&R (206) 526-6959 voice
7600 Sand Point Way NE (206) 526-6329 fax
Seattle, WA 98115 (206) 526-6317 main reception

Chris.Barker@noaa.gov

Hi George,

Most of us on this list prefere bottom post and/or interspersing, as it is easier to follow.

Maybe take a step back and write down in plain English what you want to do and what the users flow should be.

Take a little time to digest what people are suggesting and then apply it. E.g. this post shows as a reply to Tim's message but the code you show does not take into account at all what Tim suggested - so it becomes difficult to follow (at least for me).

I had to tell where my directory was in your code and tried:
        def checkBtnClick2(self, evt):
                if self.filenames:

here you check for self.filenames which is set somewhere else.

                        folder = self.dirname
                        f = self.filename

why are you assigning something to "f" here

                        for self.filenames in os.walk(folder):

here you walk the folder and assign again to self.filenames, so what is the check above for? Also check out what "os.walk" returns!

                                for f in self.filenames:
                                        if not f.startswith('.') and f.find(',') >= 0:
                                                os.rename( f, f.replace(',', '') )
I get: 'list' object has no attribute 'startswith'

self.filenames here does NOT contain filenames but it contains what "os.walk" returned and as you only provided one variable in your for loop it is a list with "dirpath", "dirnames" and "filenames" as items of the list which were returned by "os.walk"

I hope this helps
Werner

P.S.
Chris' suggestion of using a debugger is something you should consider and spend some time to find the IDE which fits you.

A few suggestions:
- WingIDE
- Boa Constructor
- pyCharm

There are many more:
http://wiki.wxpython.org/wxPythonPit%20Apps#Programming:_Editors.2C_IDE.27s_and_other_tools

···

On 15/08/2013 23:58, George McCown wrote:

George McCown wrote:

I had to tell where my directory was in your code and tried:

        def checkBtnClick2(self, evt):
                if self.filenames:
                        folder = self.dirname
                        f = self.filename
                        for self.filenames in os.walk(folder):
                                for f in self.filenames:
                                        if not f.startswith('.') and
f.find(',') >= 0:
                                                os.rename( f,
f.replace(',', '') )

I get: 'list' object has no attribute 'startswith'

Of course you do. You're throwing code together without thinking about
what it does. You already HAVE a list of filenames, in self.filenames.
But right in the middle of this code, you overwrite that list by
assigning the result of os.walk to it. Similarly, you save
    f = self.filename
and then, in the loop, you overwrite f again.

Have you looked at the documentation for os.walk to see what it
returns? You are not using it correctly.

So, what EXACTLY are you trying to do? Are you trying to fix the names
that are held in self.filenames? Or are you trying to fix the names of
the files in the tree starting at self.dirname? That is two very
different targets.

If ALL you want to do here is fix the names of the folders in the
directory tree starting at "self.dirname", then you don't care about
self.filename and self.filenames at all. That code would be:

def checkBtnClick2(self, evt):
    for dirpath, dirs, files in os.walk(self.dirname):
        for f in files:
            if not f.startswith('.') and f.find(',') >= 0:
                full = os.path.join( dirpath, f )
                os.rename( full, full.replace(',', '') )

···

--
Tim Roberts, timr@probo.com
Providenza & Boekelheide, Inc.

Tim Roberts wrote:

If ALL you want to do here is fix the names of the folders in the
directory tree starting at "self.dirname", then you don't care about
self.filename and self.filenames at all. That code would be:

def checkBtnClick2(self, evt):
    for dirpath, dirs, files in os.walk(self.dirname):
        for f in files:
            if not f.startswith('.') and f.find(',') >= 0:
                full = os.path.join( dirpath, f )
                os.rename( full, full.replace(',', '') )

And, actually, if you're using os.walk instead of os.listdir, then the
list of files will never contain "." and "..", so the first check is silly:
            if f.find(',') >= 0:

REMEMBER, however, that this assumes you have something meaningful in
self.dirpath when the button is pressed. There won't be anything
magically placed there. You have to have PUT something there.

···

--
Tim Roberts, timr@probo.com
Providenza & Boekelheide, Inc.

I got another answer that works very well.

http://stackoverflow.com/questions/18264517/rename-list-files-cannot-find-files

···

On Friday, August 16, 2013 1:04:25 PM UTC-5, Tim Roberts wrote:

Tim Roberts wrote:

If ALL you want to do here is fix the names of the folders in the

directory tree starting at “self.dirname”, then you don’t care about

self.filename and self.filenames at all. That code would be:

def checkBtnClick2(self, evt):

for dirpath, dirs, files in os.walk(self.dirname):
    for f in files:
        if not f.startswith('.') and f.find(',') >= 0:
            full = os.path.join( dirpath, f )
            os.rename( full, full.replace(',', '') )

And, actually, if you’re using os.walk instead of os.listdir, then the

list of files will never contain “.” and “…”, so the first check is silly:

        if f.find(',') >= 0:

REMEMBER, however, that this assumes you have something meaningful in

self.dirpath when the button is pressed. There won’t be anything

magically placed there. You have to have PUT something there.


Tim Roberts, ti...@probo.com

Providenza & Boekelheide, Inc.

Hi George,

···

On 16/08/2013 22:47, George McCown wrote:

I got another answer that works very well.
python - Rename list files cannot find files - Stack Overflow

If that works for you, great, but note that this is basically the same answer Tim gave to you too.

Werner