copy a file from packaged(.exe)

40 views
Skip to first unread message

rajarame...@gmail.com

unread,
Oct 28, 2021, 11:40:27 AM10/28/21
to Kivy users support
Hi All,

Is it possible to copy a file(which included in .exe while packaging ) from python.exe on to desktop.

Thanks,
Raja

Elliot Garbus

unread,
Oct 28, 2021, 12:09:06 PM10/28/21
to kivy-...@googlegroups.com

Yes.

In this program, https://github.com/ElliotGarbus/BackingTrackPlayer, I have included ffmpeg.exe into the bundle and then call it using subprocess.  If you look at the spec files, https://github.com/ElliotGarbus/BackingTrackPlayer/tree/master/BackingTrackPlayerDist you can see ffmpeg was included into the “datas” section, and copied to the current working directory.

 

I expect you could do something similar and then from python copy the code to the desktop, or just do it with the pyinstaller code, by setting the destination to dir in the datas to the desktop path.

--
You received this message because you are subscribed to the Google Groups "Kivy users support" group.
To unsubscribe from this group and stop receiving emails from it, send an email to kivy-users+...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/kivy-users/ef945d7c-7b4f-4039-a9b7-f2c90490ecb6n%40googlegroups.com.

 

Raja Ramesh

unread,
Oct 29, 2021, 6:18:42 AM10/29/21
to kivy-...@googlegroups.com
i will check and get back to you Elliot...

Raja Ramesh

unread,
Oct 31, 2021, 1:05:10 AM10/31/21
to kivy-...@googlegroups.com
Hi Elliot,

I had a look on BackingTrackPlayerDist file and ffmpeg.exe was included into the “datas” section. But in the main.py, there is no subprocess method calling ffmpeg.exe  nor coping ffmpeg.exe.. onto the local desktop.

Assume, I have a test.txt file with some content( which accepts inputs entered in one file.exe) and I created one_file.exe by including test.txt in datas section of the .spec file. Now when I run one_file.exe it should update the content in the text.txt with the values entered in one file.exe and copy the test.txt file which we included in datas section of the .spec file onto the local desktop. everything should happen at runtime.  

Thanks,
Raja

On Thu, Oct 28, 2021 at 9:39 PM Elliot Garbus <elli...@cox.net> wrote:

Elliot Garbus

unread,
Oct 31, 2021, 2:18:10 AM10/31/21
to kivy-...@googlegroups.com
Ffmpeg.exe is copied to the current working directory by pyinstaller it is called in playscreen.py 

See: def _generate_time_stretch

You should have no trouble doing what you described. 


Sent from my iPhone

On Oct 30, 2021, at 10:05 PM, Raja Ramesh <rajarame...@gmail.com> wrote:



Raja Ramesh

unread,
Oct 31, 2021, 12:09:41 PM10/31/21
to kivy-...@googlegroups.com
I will go through the code again...

Elliot Garbus

unread,
Oct 31, 2021, 1:14:51 PM10/31/21
to kivy-...@googlegroups.com

I’d encourage you to create a simple test case. 

I typically create a one dir build, and on windows I use inno setup to create a windows installer.

 

If you are doing a one_file building in py installer, there are additional actions you need to take to access data files.

See: https://pyinstaller.readthedocs.io/en/stable/runtime-information.html#run-time-information

Raja Ramesh

unread,
Nov 6, 2021, 11:31:09 PM11/6/21
to kivy-...@googlegroups.com
Hi Elliot,

I am able to copy the .txt file to the desktop from .exe(one file). now how to update the .txt file with values entered on the screen. I am using the code below.

from kivy.app import App
from kivy.lang import Builder
from kivy.uix.boxlayout import BoxLayout

import os
from pathlib import Path
from shutil import copyfile

kv= '''
<check>:
FloatLayout:
Label:
text: 'a:'
font_size: 20
size_hint: .1,.1
pos_hint: {'x':.3, 'y': .5}
TextInput:
id: 'a_ti'
hint_text:'enter text'
size_hint: .3,.1
pos_hint: {'x':.4, 'y': .5}

Label:
text: 'b:'
font_size: 20
size_hint: .1,.1
pos_hint: {'x':.3, 'y': .4}
TextInput:
id: 'b_ti'
hint_text:'enter text'
size_hint: .3,.1
pos_hint: {'x':.4, 'y': .4}

Button:
text: 'Proceed'
size_hint: .2,.1
pos_hint: {'x':.6, 'y': .2}
on_press:
root.copy_file_to_desktop()
check:
id: conn
'''
class check (BoxLayout):

def copy_file_to_desktop(self):
exe_path = Path(__file__).parent / 'sample.txt'
print(f'exe_path is:-{exe_path}')
filename= 'sample.txt'
dest_path = os.path.join(os.path.expanduser('~\Desktop'),filename)
print('started file copy...')
copyfile(exe_path, dest_path)
print('file copy completed...')

class test(App):
def build(self):
return Builder.load_string(kv)

#executing
test().run()

Thanks,
Raja

sample_txt.PNG
screen.PNG

Elliot Garbus

unread,
Nov 7, 2021, 9:47:04 AM11/7/21
to kivy-...@googlegroups.com

I expanded your example to add a button to update the file.

I open the file on the desktop and update the data.  I parsed the file and updated the data.  If you have flexibility in your file format I would encourage you to use JSON this could provide a more robust solution.  The simple parsing I did in the example can fail in a number of cases, but is sufficient for demonstration.

 

 

from kivy.app import App
from kivy.lang import Builder
from kivy.uix.boxlayout import BoxLayout

import os
from pathlib import Path
from shutil import copyfile

kv =
'''

<check>:
    FloatLayout:
        Label:
            text: 'a:'
            font_size: 20
            size_hint: .1,.1
            pos_hint: {'x':.3, 'y': .5}
        TextInput:
            id: a_ti                # id values are identifiers not strings

            hint_text:'enter text'
            size_hint: .3,.1
            pos_hint: {'x':.4, 'y': .5}

        Label:
            text: 'b:'
            font_size: 20
            size_hint: .1,.1
            pos_hint: {'x':.3, 'y': .4}
        TextInput:
            id: b_ti
            hint_text:'enter text'
            size_hint: .3,.1
            pos_hint: {'x':.4, 'y': .4}

        BoxLayout:

            pos_hint: {'x':.6, 'y': .2}
            Button:
                text: 'copy to DT'
                size_hint: None, None
                size: 100, 48
                on_press:
                    root.copy_file_to_desktop()
            Button:
                text: 'Update File'
                size_hint: None, None
                size: 100, 48
                on_release: root.update_file(a_ti.text, b_ti.text)
check:
    id: conn
'''


class check(BoxLayout):

   
def copy_file_to_desktop(self):
        exe_path = Path(__file__).parent /
'sample.txt'
       
print(f'exe_path is:-{exe_path}')
        filename =
'sample.txt'
       
dest_path = os.path.join(os.path.expanduser('~\Desktop'), filename)
       
print('started file copy...')
        copyfile(exe_path, dest_path)
       
print('file copy completed...')

   
def update_file(self, a, b):
        dest_path = Path(
'~\Desktop').expanduser() / 'sample.txt'
       
if not dest_path.exists():
           
return
        with
open(dest_path) as f:
            lines = f.readlines()
        line_a = lines[
0].split('=')
        line_a[
1] = f'= {a}'
       
line_b = lines[1].split('=')
        line_b[
1] = f'= {b}'
       
new_data = ''.join(line_a) + '\n' + ''.join(line_b)
       
with open(dest_path, 'w') as f:
            f.write(new_data)


class TestApp(App):
   
def build(self):
       
return Builder.load_string(kv)


# executing
TestApp().run()

Raja Ramesh

unread,
Nov 7, 2021, 12:22:26 PM11/7/21
to kivy-...@googlegroups.com
Hi Elliot,

i am trying to create .ini file at runtime with the help of get_application_config() in main.py (BackingTrackPlayerDist) but .ini file is not creating. how to create .ini file at runtime similar to BackingTrackPlayerDist

Thanks,
Raja

Elliot Garbus

unread,
Nov 7, 2021, 3:09:24 PM11/7/21
to kivy-...@googlegroups.com

The use of an application configuration file is described here: https://kivy.org/doc/stable/api-kivy.app.html?highlight=build_config#application-configuration

 

Here is how the config file works in BackingTrackPlayer.

In the file main.py:

The method build_config() is called prior to on_start().  Looking specifically at BackingtrackPlayer, as an example:



    def build_config(self, config):
        config.setdefaults('MIDI', {'input': 'None',
                                    'channel': 'None'})
        config.setdefaults('Track', {'song': 'None'})
        config.setdefaults('Window', {'width': window_width,
                                      'height': window_height,
                                      'top': window_top,
                                      'left': window_left})
        config.setdefaults('Recent Tracks', {'tracks': ''})

 

I am using setdefaults() to create the initial values of the ini file.  If the file does not exist, it will be initialized with the values provided here.  See: https://kivy.org/doc/stable/api-kivy.config.html?highlight=setdefaults#kivy.config.ConfigParser.setdefaults

 

In the on_stop method, the key parameters for the app are collected from the app and written to the config file:

    def on_stop(self):
        p = self.root.ids.sm.get_screen('play_screen').track_path
        # update config file
        if p:
            self.config.set('Track', 'song', p)
            tracks = ','.join(self.recent_track_paths)
            self.config.set('Recent Tracks', 'tracks', tracks)
            self.config.write()
        if self.mc.midi_in_port and self.mc.midi_channel is not None:
            self.config.set('MIDI', 'input', self.mc.midi_in_port.name)
            self.config.set('MIDI', 'channel', self.mc.midi_channel)
            self.config.write()
        # clean up old files
        if p:
            fn = Path(p)
            suffix = fn.suffix
            speed_dir = Path(self.user_data_dir) / 'speeds'
            for f in speed_dir.glob('*'):
                if f.stem[:-4] + suffix != fn.name:
                    f.unlink()  # remove files not related to current track
 
 

The code in get_application_config returns the path to the .ini file.  This is the full path to the .ini file.  I have changed the path to put it where I want on Windows and MacOS. 



    def get_application_config(self, defaultpath='%(appdir)s/%(appname)s.ini'):
        if platform == 'win' or platform == 'macosx':    # mac will not write into app folder
            s = self.user_data_dir + '/%(appname)s.ini'  # puts ini in AppData on Windows
        else:
            s = defaultpath
        return super().get_application_config(defaultpath=s)

 

I also save the position and size of the Window.  This is described here:

https://github.com/ElliotGarbus/KivyWindowSize

Raja Ramesh

unread,
Nov 8, 2021, 6:18:29 AM11/8/21
to kivy-...@googlegroups.com
Thank you Elliot for sharing the details.

Raja Ramesh

unread,
Nov 8, 2021, 10:57:27 AM11/8/21
to kivy-...@googlegroups.com
Hi Elliot,

I am trying to update the .ini file with the text entered in TextInput with below code. But i am getting
'key3': self.root.ids.ti.text
 AttributeError: 'NoneType' object has no attribute 'ids'

from kivy.app import App
from kivy.lang import Builder

import os

kv='''
FloatLayout:
Label:
text: 'Value:'
size_hint: .2,.1
pos_hint: {'x': .2, 'y':.5}
TextInput:
id: ti
hint_text: 'Enter Text'
size_hint: .2,.1
pos_hint: {'x': .35, 'y':.5}
'''

class TestApp(App):

def __init__(self, **kwargs):
super().__init__(**kwargs)

def build_config(self, config):
config.setdefaults('section1', {
'key1': 'value1',
'key2': '42',
'key3': self.root.ids.ti.text
})

def get_application_config(self):
s = os.path.join(os.path.expanduser('~\Desktop'), 'checkcopy.ini')
return super(TestApp, self).get_application_config(s)

def build(self):
return Builder.load_string(kv)

TestApp().run()

Thanks,
Raja

Elliot Garbus

unread,
Nov 8, 2021, 11:32:40 AM11/8/21
to kivy-...@googlegroups.com

I have expanded your example.  Let me know if this helps.

 

from kivy.app import App
from kivy.lang import Builder

import os

kv=
'''
FloatLayout:
    BoxLayout:
        pos_hint: {'center_x': 0.5, 'center_y': 0.5}
        size_hint_y: None
        height: dp(48)
        Label:
            text: 'Value:'

        TextInput:
            id: ti
            hint_text: 'Enter Text'
        Button:
            text: 'Set Config Value'
            on_release: app.update_config(ti.text)
'''

class TestApp(App):

   
def __init__(self, **kwargs):
       
super().__init__
(**kwargs)

   
def build_config(self, config):      # This sets defaults if config does not exist
       
config.setdefaults('section1', {
           
'key1': 'value1',
           
'key2': '42',
           
'key3': 'Initial Text'      # Build config is called before the kv code is processed.
       
})

   
def get_application_config(self):
        s = os.path.join(os.path.expanduser(
'~\Desktop'), 'checkcopy.ini')
       
return super(TestApp, self).get_application_config(s)

   
def build(self):
       
return Builder.load_string(kv)

   
def on_start(self):
        text =
self.config.get('section1','key3')
       
self.root.ids.ti.text = text  # set value of textinput with data from config

   
def update_config(self, text):
       
self.config.set('section1', 'key3', text)  # update the config
       
self.config.write()                        # write the config to the file


TestApp().run()

Raja Ramesh

unread,
Nov 15, 2021, 1:04:53 AM11/15/21
to kivy-...@googlegroups.com
Thank you Elliot for sharing th details. It helps a lot.

You received this message because you are subscribed to a topic in the Google Groups "Kivy users support" group.
To unsubscribe from this topic, visit https://groups.google.com/d/topic/kivy-users/awm-CKkXRiI/unsubscribe.
To unsubscribe from this group and all its topics, send an email to kivy-users+...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/kivy-users/61895122.1c69fb81.71f20.89f8SMTPIN_ADDED_MISSING%40gmr-mx.google.com.

Raja Ramesh

unread,
Nov 18, 2021, 11:50:23 AM11/18/21
to kivy-...@googlegroups.com
Hi Elliot,

I am trying to type commands on putty with the help of pyautogui and pywinauto python libraries.But there are limitations. So, Is there any other way to type commands when putty is minimized?  

Thanks,
Raja

You received this message because you are subscribed to a topic in the Google Groups "Kivy users support" group.
To unsubscribe from this topic, visit https://groups.google.com/d/topic/kivy-users/awm-CKkXRiI/unsubscribe.
To unsubscribe from this group and all its topics, send an email to kivy-users+...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/kivy-users/61895122.1c69fb81.71f20.89f8SMTPIN_ADDED_MISSING%40gmr-mx.google.com.

Elliot Garbus

unread,
Nov 18, 2021, 9:19:58 PM11/18/21
to kivy-...@googlegroups.com

I have no idea.  I have not used putty, or the libraries you’ve mentioned.   I would not expect that an app would accept input when it is minimized.

Reply all
Reply to author
Forward
0 new messages