Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

non-blocking getkey?

142 views
Skip to first unread message

Ulli Horlacher

unread,
Nov 18, 2015, 3:39:34 AM11/18/15
to
In my program (for python 2.7) the user must enter file names with
mouse copy+paste. I use:

while True:
file = raw_input(prompt)
if file == '': break
files.append(file)

The problem now is: my users do not hit ENTER after pasting.
The file names are pasted together in one single line without space or
other delimiter.

My idea now is: instead of raw_input() I use a get_paste() function, which
reads input character for input character and after a (say) 1 s timeout it
returns the string. Pasting a string with the mouse is rather fast, there
should be no big delay between the characters.

How can I implement such a get_paste() function?
I need a non-blocking getkey() function.

It must work on Windows and Linux.


--
Ullrich Horlacher Server und Virtualisierung
Rechenzentrum IZUS/TIK E-Mail: horl...@tik.uni-stuttgart.de
Universitaet Stuttgart Tel: ++49-711-68565868
Allmandring 30a Fax: ++49-711-682357
70550 Stuttgart (Germany) WWW: http://www.tik.uni-stuttgart.de/

Christian Gollwitzer

unread,
Nov 18, 2015, 4:15:16 AM11/18/15
to
Am 18.11.15 um 09:39 schrieb Ulli Horlacher:
> In my program (for python 2.7) the user must enter file names with
> mouse copy+paste. I use:
>
> while True:
> file = raw_input(prompt)
> if file == '': break
> files.append(file)
>
> How can I implement such a get_paste() function?
> I need a non-blocking getkey() function.
> It must work on Windows and Linux.

Non-blocking I/O from the commandline is OS specific. There are
different solutions, and it's usually hacky (stty on Linux, Console API
on Windows)

Why do you not use a proper GUI toolkit to do this? It is
straight-forward to accept keystrokes, copy/paste and drag'n'drop with
most toolkits. Especially if you target Windows users, I think they
would be more than happy to get a GUI app then to open a terminal window
and paste something there. The standard terminal on Windows is very
ugly, can't resize the width, and pasting works only if you right-click
-> paste.

Christian

Ulli Horlacher

unread,
Nov 18, 2015, 5:40:09 AM11/18/15
to
Christian Gollwitzer <auri...@gmx.de> wrote:

> > How can I implement such a get_paste() function?
> > I need a non-blocking getkey() function.
> > It must work on Windows and Linux.
>
> Non-blocking I/O from the commandline is OS specific. There are
> different solutions, and it's usually hacky (stty on Linux, Console API
> on Windows)

A "if windows (...) else linux (...)" solution is ok, I have such
distinction already at several places in my code.

Do you have example code for non-blocking I/O?


> Why do you not use a proper GUI toolkit to do this?

it is too complicated to rewrite my application from CLI to GUI.
But... is there a windows program with which one can select files and the
result is written to STDOUT?
Then I could use pipe open in my Python program.


> The standard terminal on Windows is very ugly, can't resize the width,
> and pasting works only if you right-click -> paste.

You can also use drag&drop. This is ok for my users.

Ulli Horlacher

unread,
Nov 18, 2015, 6:02:12 AM11/18/15
to
Ulli Horlacher <fram...@rus.uni-stuttgart.de> wrote:

> it is too complicated to rewrite my application from CLI to GUI.
> But... is there a windows program with which one can select files and the
> result is written to STDOUT?

Found it:

from Tkinter import Tk
from tkFileDialog import askopenfilename

Tk().withdraw()
file = askopenfilename()


Hey, easy! :-)

Christian Gollwitzer

unread,
Nov 18, 2015, 6:17:20 AM11/18/15
to
Am 18.11.15 um 12:01 schrieb Ulli Horlacher:
> Ulli Horlacher <fram...@rus.uni-stuttgart.de> wrote:
>
>> it is too complicated to rewrite my application from CLI to GUI.
>> But... is there a windows program with which one can select files and the
>> result is written to STDOUT?
>
> Found it:
>
> from Tkinter import Tk
> from tkFileDialog import askopenfilename
>
> Tk().withdraw()
> file = askopenfilename()
>
>
> Hey, easy! :-)
>

Welcome to GUI programming ;) Do you still have other data to input?
There are nice tutorials at http://tkdocs.com and for simple input like
a single number or a line of text, there is a module simpledialog

Christian

Terry Reedy

unread,
Nov 18, 2015, 7:26:57 AM11/18/15
to
On 11/18/2015 6:01 AM, Ulli Horlacher wrote:
> Ulli Horlacher <fram...@rus.uni-stuttgart.de> wrote:
>
>> it is too complicated to rewrite my application from CLI to GUI.
>> But... is there a windows program with which one can select files and the
>> result is written to STDOUT?
>
> Found it:
>
> from Tkinter import Tk
> from tkFileDialog import askopenfilename
>
> Tk().withdraw()
> file = askopenfilename()

To get multiple names, add 's'. On Windows, one uses control-leftclick
to get multiple names. Don't know about other systems.

>>> fd.askopenfilenames() # ^click 4 names
('F:/Python/dev/27/Lib/idlelib/aboutDialog.py',
'F:/Python/dev/27/Lib/idlelib/AutoComplete.py',
'F:/Python/dev/27/Lib/idlelib/AutoCompleteWindow.pyc',
'F:/Python/dev/27/Lib/idlelib/Bindings.py')

The limitation is that this will not work if any of the file names
contain astral (non-BMP) chars because tk cannot handle such characters.

--
Terry Jan Reedy

Ulli Horlacher

unread,
Nov 18, 2015, 8:06:42 AM11/18/15
to
Terry Reedy <tjr...@udel.edu> wrote:

> > from Tkinter import Tk
> > from tkFileDialog import askopenfilename
> >
> > Tk().withdraw()
> > file = askopenfilename()
>
> To get multiple names, add 's'.

I have found it already, thanks.


> The limitation is that this will not work if any of the file names
> contain astral (non-BMP) chars because tk cannot handle such characters.

What are "astral chars"?

But anyway, askopenfilename() is a dead end for me: one cannot select
directories with it, just plain files.
In my application the user MUST select files and directories (in one go).

Chris Angelico

unread,
Nov 18, 2015, 8:24:45 AM11/18/15
to
On Thu, Nov 19, 2015 at 12:06 AM, Ulli Horlacher
<fram...@rus.uni-stuttgart.de> wrote:
>> The limitation is that this will not work if any of the file names
>> contain astral (non-BMP) chars because tk cannot handle such characters.
>
> What are "astral chars"?

Characters not on the Basic Multilingual Plane (BMP). The Unicode
character set is divided into a number of planes of 65,536 codepoints
each, with the most commonly used ones on the first plane, the BMP. A
lot of programs either cannot use non-BMP characters or have problems
with them; for instance, anything that uses UTF-16 as its internal
representation (ECMAScript, notably; also Python 2 on Windows) sees
astral characters as pairs of code points.

> In my application the user MUST select files and directories (in one go).

It's extremely uncommon to be able to select a combination of files
and directories. The UI for this would be quite annoying, I think. You
may find it easier to have your own wrapper; for example, have a list
of selected files/directories, with buttons "Add File" and "Add
Directory" underneath. The former would use askopenfilenames (despite
the singular in the button name), and the latter would use
askdirectory. Trying to do both at once would be hard.

ChrisA

Steven D'Aprano

unread,
Nov 18, 2015, 8:38:39 AM11/18/15
to
On Thu, 19 Nov 2015 12:06 am, Ulli Horlacher wrote:

> Terry Reedy <tjr...@udel.edu> wrote:
>
>> > from Tkinter import Tk
>> > from tkFileDialog import askopenfilename
>> >
>> > Tk().withdraw()
>> > file = askopenfilename()
>>
>> To get multiple names, add 's'.
>
> I have found it already, thanks.
>
>
>> The limitation is that this will not work if any of the file names
>> contain astral (non-BMP) chars because tk cannot handle such characters.
>
> What are "astral chars"?

Unicode characters beyond U+FFFF.

Unicode covers the entire range of code points (informally characters, don't
worry about the technical difference) from U+0000 to U+10FFFF. The part
following the "U+" is the numeric ordinal value, written in hexadecimal.

Some older versions of Unicode only included 2**16 == 65536 distinct
characters, but many years ago Unicode was extended far beyond that number.
But the first 65536 characters are called the "Basic Multilingual Plane".
All the rest are in the "Supplementary Multilingual Planes", which being a
mouthful to say and write, often gets abbreviated as "astral planes". Hence
the characters themselves are called "astral characters".

Even today, some programming languages and systems have difficulty dealing
with characters that require more than two bytes.

--
Steven

Ulli Horlacher

unread,
Nov 18, 2015, 8:51:46 AM11/18/15
to
Steven D'Aprano <st...@pearwood.info> wrote:

> >> The limitation is that this will not work if any of the file names
> >> contain astral (non-BMP) chars because tk cannot handle such characters.
> >
> > What are "astral chars"?
>
> Unicode characters beyond U+FFFF.

I see, for very exotic character sets, like Klingon, etc :-)
In my case, I can simple ignore them.


> Unicode covers the entire range of code points (informally characters, don't
> worry about the technical difference) from U+0000 to U+10FFFF. The part
> following the "U+" is the numeric ordinal value, written in hexadecimal.

That was my knowledge so far.


> Some older versions of Unicode only included 2**16 == 65536 distinct
> characters, but many years ago Unicode was extended far beyond that number.
> But the first 65536 characters are called the "Basic Multilingual Plane".
> All the rest are in the "Supplementary Multilingual Planes", which being a
> mouthful to say and write, often gets abbreviated as "astral planes". Hence
> the characters themselves are called "astral characters".

And this was new to me. Learned :-)

Ulli Horlacher

unread,
Nov 18, 2015, 8:58:07 AM11/18/15
to
Chris Angelico <ros...@gmail.com> wrote:

> > In my application the user MUST select files and directories (in one go).
>
> It's extremely uncommon to be able to select a combination of files
> and directories.

I have an uncommon application :-)
Filetransfer of ANY size: http://fex.rus.uni-stuttgart.de:8080/


> The UI for this would be quite annoying, I think. You may find it easier
> to have your own wrapper; for example, have a list of selected
> files/directories, with buttons "Add File" and "Add Directory"
> underneath.

I came (independantly) to the same solution!
So it must be a good idea :-)

http://fex.rus.uni-stuttgart.de:8080/fop/3yxsCacS/X-20151118145221.png

Chris Angelico

unread,
Nov 18, 2015, 9:01:53 AM11/18/15
to
On Thu, Nov 19, 2015 at 12:51 AM, Ulli Horlacher
<fram...@rus.uni-stuttgart.de> wrote:
> Steven D'Aprano <st...@pearwood.info> wrote:
>
>> >> The limitation is that this will not work if any of the file names
>> >> contain astral (non-BMP) chars because tk cannot handle such characters.
>> >
>> > What are "astral chars"?
>>
>> Unicode characters beyond U+FFFF.
>
> I see, for very exotic character sets, like Klingon, etc :-)
> In my case, I can simple ignore them.

And other exotic character sets, like Chinese.

https://en.wikipedia.org/wiki/CJK_Unified_Ideographs#CJK_Unified_Ideographs_Extension_B

But I'm sure you can ignore them, too. Hardly anyone on this planet
speaks Chinese.

ChrisA

Jussi Piitulainen

unread,
Nov 18, 2015, 9:14:11 AM11/18/15
to
Ulli Horlacher writes:
> Steven D'Aprano wrote:
>
>> >> The limitation is that this will not work if any of the file names
>> >> contain astral (non-BMP) chars because tk cannot handle such
>> >> characters.
>> >
>> > What are "astral chars"?
>>
>> Unicode characters beyond U+FFFF.
>
> I see, for very exotic character sets, like Klingon, etc :-)
> In my case, I can simple ignore them.

Better test how your user interface behaves when a user copy-pastes one
of those characters into it. If it merely garbles the character somehow,
you may be able to ignore the problem, but if it promptly shuts down
your whole application and loses some unfinished work, the user may not
be happy.

Klingon may not be that widely spoken, but all manner of little picture
characters seem popular. Wasn't one just chosen to be the Word Of The
Year? And when it's the underlying GUI library that crashes, it's too
late for your program to sanitize the input.

Ulli Horlacher

unread,
Nov 18, 2015, 11:50:23 AM11/18/15
to
Ulli Horlacher <fram...@rus.uni-stuttgart.de> wrote:

> from Tkinter import Tk
> from tkFileDialog import askopenfilename
>
> Tk().withdraw()
> file = askopenfilename()

I found another glitch:

After termination of askopenfilename() the window focus is not returned to
the calling window (xterm on Linux, cmd on Windows). I have to click it
again, to regain the focus and continue typing. Is there a workaround?

Terry Reedy

unread,
Nov 18, 2015, 12:56:36 PM11/18/15
to
On 11/18/2015 11:50 AM, Ulli Horlacher wrote:
> Ulli Horlacher <fram...@rus.uni-stuttgart.de> wrote:
>
>> from Tkinter import Tk
>> from tkFileDialog import askopenfilename
>>
>> Tk().withdraw()
>> file = askopenfilename()
>
> I found another glitch:
>
> After termination of askopenfilename() the window focus is not returned to
> the calling window (xterm on Linux, cmd on Windows). I have to click it
> again, to regain the focus and continue typing. Is there a workaround?

What happens with

root = Tk()
root.withdraw()
fiel = ...
root.destroy()

Focus cannot stay with destroyed window.

--
Terry Jan Reedy

eryksun

unread,
Nov 18, 2015, 1:25:09 PM11/18/15
to
On Wed, Nov 18, 2015 at 3:14 AM, Christian Gollwitzer <auri...@gmx.de> wrote:
> The standard terminal on Windows is very ugly, can't resize the width, and
> pasting works only if you right-click -> paste.

The console UI is improved in Windows 10:
http://blogs.windows.com/buildingapps/2014/10/07/console-improvements-in-the-windows-10-technical-preview

Ulli Horlacher

unread,
Nov 19, 2015, 10:48:18 AM11/19/15
to
The focus is moved to another, unrelated window, but not back to the
window in which the python scripts run.
Same behaviour on Linux (XFCE) and windows 7.

Michael Torrie

unread,
Nov 19, 2015, 11:31:35 AM11/19/15
to
On 11/19/2015 08:48 AM, Ulli Horlacher wrote:
>
> The focus is moved to another, unrelated window, but not back to the
> window in which the python scripts run.
> Same behaviour on Linux (XFCE) and windows 7.

That's because an app that communicates with standard in and standard
out could be running over telnet, theoretically, so there would be no
window at all. There's absolutely no link in stdin and stdout to a
graphical window. It's not even possible on Windows as the console
subsystem is completely separate from the GUI subsystem. When your app
opens a Tk window, it's creating a brand new, top-level window, not
associated with any existing window.

One windows it might be possible to use the win32 api to enumerate the
windows, find your console window and switch to it. Might even be
possible on Linux using raw X11 calls.







eryksun

unread,
Nov 20, 2015, 3:44:11 AM11/20/15
to
On Thu, Nov 19, 2015 at 10:31 AM, Michael Torrie <tor...@gmail.com> wrote:
> One windows it might be possible to use the win32 api to enumerate the
> windows, find your console window and switch to it.

You can call GetConsoleWindow [1] and then SetForegroundWindow [2].

import os
import sys

try:
import tkinter
from tkinter import filedialog
except ImportError:
import Tkinter as tkinter
import tkFileDialog as filedialog
input = raw_input

if sys.platform == 'win32':
import ctypes

kernel32 = ctypes.WinDLL('kernel32')
user32 = ctypes.WinDLL('user32')

def setfgwin():
hcon = kernel32.GetConsoleWindow()
if hcon and user32.SetForegroundWindow(hcon):
return True
return False

def get_filename():
filename = filedialog.askopenfilename()
setfgwin()
return os.path.normpath(filename)

if __name__ == '__main__':
root = tkinter.Tk()
root.withdraw()
filename = get_filename()
print('filename: %s' % filename)
input('press enter...')

[1]: https://msdn.microsoft.com/en-us/library/ms683175
[2]: https://msdn.microsoft.com/en-us/library/ms633539

Ulli Horlacher

unread,
Nov 23, 2015, 12:02:08 PM11/23/15
to
eryksun <ery...@gmail.com> wrote:
> On Thu, Nov 19, 2015 at 10:31 AM, Michael Torrie <tor...@gmail.com> wrote:
> > One windows it might be possible to use the win32 api to enumerate the
> > windows, find your console window and switch to it.
>
> You can call GetConsoleWindow [1] and then SetForegroundWindow [2].
(...)

Sorry, for the late feedback:
great, this works! Thanks!

Ulli Horlacher

unread,
Nov 28, 2015, 5:30:10 AM11/28/15
to
Ulli Horlacher <fram...@rus.uni-stuttgart.de> wrote:
> eryksun <ery...@gmail.com> wrote:
> > On Thu, Nov 19, 2015 at 10:31 AM, Michael Torrie <tor...@gmail.com> wrote:
> > > One windows it might be possible to use the win32 api to enumerate the
> > > windows, find your console window and switch to it.
> >
> > You can call GetConsoleWindow [1] and then SetForegroundWindow [2].
> (...)
>
> great, this works! Thanks!

One of my Windows test users reports, that the file dialog window of
askopenfilename() starts behind the console window and has no focus.
On Linux (XFCE) I do not have this problem.

I start it with:

Tk().withdraw()
file = askopenfilename(title='select a file',initialdir=HOME)
set_window_focus() # give focus back to console window

Can one force askopenfilename() to start in foreground with focus?

Christian Gollwitzer

unread,
Nov 28, 2015, 6:45:34 AM11/28/15
to
Am 28.11.15 um 11:29 schrieb Ulli Horlacher:
> One of my Windows test users reports, that the file dialog window of
> askopenfilename() starts behind the console window and has no focus.
> On Linux (XFCE) I do not have this problem.
>
> I start it with:
>
> Tk().withdraw()
> file = askopenfilename(title='select a file',initialdir=HOME)
> set_window_focus() # give focus back to console window
>
> Can one force askopenfilename() to start in foreground with focus?

I can't test it right now, but I think it /should/ go into the
foreground by itself. For a toplevel window, which you create manually,
there is a lift() method which asks the OS to move the window to the
top. But on Windows, this file dialog is a native call and cannot be
influenced that much.

I see two thingd:

1) Tk().withdraw()

- this seems odd to me, because you don't keep a reference to the Tk
object around. Better do

root=Tk()
roo.withdraw()

2) Maybe it helps if you inject an update() after the withdraw(), maybe not

root.update()

3) I can confirm, that also on OSX the file dialog does not raise above
the console window, though it is not as bad because the dialog window is
muhc bigger then the console window.

I think that you are curing a lot of symptoms with the focus setting to
the console etc. Many problems would simply go away if you wrote the
whole thing as a GUI program. If I understand correctly, what you want -
a program to select files and folders to upload to your server - then
this would not be that much more work than the CLI with input() which
you are writing, and definitely less work to get it correct than the
plastering of the symptoms.

For example, a very simple approach would use a listbox with a + and a -
button. upon hitting - (or the delete key), you delete the selected
entries. Upon hitting +, you pop up the file selection dialog. upon
hitting a Go button, you send the files to the server. A minimalistic
version of it is included below. That is less then 50 lines of code,
including comments, without all the focus problems, providing a standard
desktop GUI metaphor. I haven't seen your command line code, but I doubt
that it is significantly simpler.

Of course, the code below can still use a great deal of polishing, like
scrollbars for the listbox, allowing multiple selection both for the
file dialog and the listbox, nice icons for the buttons, trapping the
close button on the main window with an "are you sure?"-type question,
maybe wrapping it up in a class, a progress bar during the upload and a
way to interrupt it... which is left as an exercise to the reader.

Christian

=================================
import Tkinter as tk, tkFileDialog as fd, ttk
from Tkinter import N,S,W,E
# create one ttk::frame to fill the main window
root=tk.Tk()
main=ttk.Frame(master=root)
# tell the pack geometry manager to completely
# fill the toplevel with this frame
main.pack(fill=tk.BOTH, expand=1)

# now create a listbox and a button frame
lb=tk.Listbox(master=main)
bf=ttk.Frame(master=main)

# use the grid manager to stack them, whereby
# the listbox should expand
lb.grid(row=0, column=0, sticky=(N,S,E,W))
bf.grid(row=1, column=0, sticky=(N,S,E,W))
main.rowconfigure(0, weight=1)
main.columnconfigure(0, weight=1)

def addfile():
filename=fd.askopenfilename()
if filename:
lb.insert(tk.END, filename)

def remove(*args):
sel=lb.curselection()
if sel:
lb.delete(sel)

def submit():
print("Submitting files:")
for filename in lb.get(0,tk.END):
print("Sending %s"%filename)

# create the three buttons
btnplus=ttk.Button(master=bf, text="+", command=addfile)
btnminus=ttk.Button(master=bf, text="-", command=remove)
btngo=ttk.Button(master=bf, text="Submit", command=submit)

btnplus.pack(side=tk.LEFT)
btnminus.pack(side=tk.LEFT)
btngo.pack(side=tk.LEFT)

# bind also the delete and Backspace keys
lb.bind('<Delete>', remove)
lb.bind('<BackSpace>', remove)

root.mainloop()
===================================================



Ulli Horlacher

unread,
Nov 28, 2015, 7:49:06 AM11/28/15
to
Christian Gollwitzer <auri...@gmx.de> wrote:

> Am 28.11.15 um 11:29 schrieb Ulli Horlacher:
> > One of my Windows test users reports, that the file dialog window of
> > askopenfilename() starts behind the console window and has no focus.
> > On Linux (XFCE) I do not have this problem.
> >
> > I start it with:
> >
> > Tk().withdraw()
> > file = askopenfilename(title='select a file',initialdir=HOME)
> > set_window_focus() # give focus back to console window
> >
> > Can one force askopenfilename() to start in foreground with focus?
>
> I can't test it right now, but I think it /should/ go into the
> foreground by itself.

This is what I think, too :-)
But my test user reports me, it is not so.


> I see two thingd:
>
> 1) Tk().withdraw()
>
> - this seems odd to me, because you don't keep a reference to the Tk
> object around.

I thought, I need it for Tk initialization.
But true, it is superfluous


> I think that you are curing a lot of symptoms with the focus setting to
> the console etc.

This is done after the file selection window is closed. This works.


> Many problems would simply go away if you wrote the whole thing as a GUI
> program.

Too much hassle.
The predecessor was a Perl/Tk program and I have had to invest 90% of the
programming work into the GUI handling. No fun at all.
Now, with fexit in Python, I skipped most of these problems.
The only GUI part is the file selection.


> If I understand correctly, what you want - a program to select files and
> folders to upload to your server

This is only one of the tasks. The main menu looks:

[s] send a file or directory
[g] get a file
[c] change login data (user, server, auth-ID)
[l] login with webbrowser
[u] update fexit
[h] help
[q] quit

(with more features to come in the future)

And the CLI:

framstag@juhu:~: ./fexit.py -h
usage: fexit [-C "comment"] [-a container] file(s) recipient[,...]
example: fexit flupp.avi fram...@rus.uni-stuttgart.de
example: fexit -C "more data" -a labdata *.png x...@flupp.org,x...@flupp.org

usage: fexit FEX-download-URL
example: fexit http://fex.rus.uni-stuttgart.de/fop/jHn34yp7/flupp.avi

Christian Gollwitzer

unread,
Nov 28, 2015, 8:34:40 AM11/28/15
to
Am 28.11.15 um 13:48 schrieb Ulli Horlacher:
> Christian Gollwitzer <auri...@gmx.de> wrote:
>> Many problems would simply go away if you wrote the whole thing as a GUI
>> program.
>
> Too much hassle.
> The predecessor was a Perl/Tk program and I have had to invest 90% of the
> programming work into the GUI handling. No fun at all.

As I see it, the program consists only of user interface - or is there
any "algorithm" working behinds the scenes? Maybe you could pass the
task on to somebody who enjoys GUI programming?

> Now, with fexit in Python, I skipped most of these problems.
> The only GUI part is the file selection.
>
>
>> If I understand correctly, what you want - a program to select files and
>> folders to upload to your server
>
> This is only one of the tasks. The main menu looks:
>
> [s] send a file or directory
> [g] get a file
> [c] change login data (user, server, auth-ID)
> [l] login with webbrowser
> [u] update fexit
> [h] help
> [q] quit

All of this is easily integrated into a GUI like the one I posted (have
you tried it?), either as a button or as a menu entry. IMO the most
common GUI pattern for this kind of thing is a side-by-side view of the
directories on the server and on the client, and a button (or
drag'n'drop) to move files between both views. I understand this is not
as easy as the script posted by me - nonetheless quite doable. For an
experienced GUI script writer it'll take a weekend to get the basics
running.

> (with more features to come in the future)
>
> And the CLI:
>
> framstag@juhu:~: ./fexit.py -h
> usage: fexit [-C "comment"] [-a container] file(s) recipient[,...]
> example: fexit flupp.avi fram...@rus.uni-stuttgart.de
> example: fexit -C "more data" -a labdata *.png x...@flupp.org,x...@flupp.org
>
> usage: fexit FEX-download-URL
> example: fexit http://fex.rus.uni-stuttgart.de/fop/jHn34yp7/flupp.avi
>

This part should probably stay as it is. For a command line tool, an
scp-like interface seems well-fitting. But for guided user input, an
interface which prompts the user for input has never been a good
solution. You have to work very hard to make that convenient. Have a
look at lftp, for instance. In the end, real GUI programming will be
easier (and more accessible)

A (still) alternative solution would be an interface to the OS to make
it a remote mounted folder (works for WebDAV on any modern OS, for
instance) or a daemon, which watches and synchronizes a directory (this
is how Dropbox works). This way it feels much more integrated to the
user - they can use whatever file manager they like to do the transfer,
or even "save" from any application (like Word, Firefox, ...) into the
remote folder.

Christian

Laura Creighton

unread,
Nov 28, 2015, 11:03:13 AM11/28/15
to
Maybe Wei Li Jiang's hack will work for you?
http://stackoverflow.com/questions/3375227/how-to-give-tkinter-file-dialog-focus

But then see if it works under MacOS. I fear it will not.

Laura

Ulli Horlacher

unread,
Nov 28, 2015, 11:06:06 AM11/28/15
to
Ulli Horlacher <fram...@rus.uni-stuttgart.de> wrote:

> One of my Windows test users reports, that the file dialog window of
> askopenfilename() starts behind the console window and has no focus.

I have got a followup: this happens only with Windows XP, not with Windows
7. Therefore I will ignore this problem :-)

Ulli Horlacher

unread,
Nov 28, 2015, 11:46:04 AM11/28/15
to
Christian Gollwitzer <auri...@gmx.de> wrote:

> Am 28.11.15 um 13:48 schrieb Ulli Horlacher:
> > Christian Gollwitzer <auri...@gmx.de> wrote:
> >> Many problems would simply go away if you wrote the whole thing as a GUI
> >> program.
> >
> > Too much hassle.
> > The predecessor was a Perl/Tk program and I have had to invest 90% of the
> > programming work into the GUI handling. No fun at all.
>
> As I see it, the program consists only of user interface - or is there
> any "algorithm" working behinds the scenes?

There is a lot of "algorithms", about 50 kB of code:
- resuming upload and download after link failures
- sending multiple files as zip or tar containers
- deleting files
- configuring login
- handling HTTP proxy
- many other things...


> Maybe you could pass the task on to somebody who enjoys GUI programming?

No, I then have to maintain it. I do not like to support foreign code. I
was in this situation already. The client was written in Java, which I do
not know. I have had to throw it away some day, because I was not able to
fix the bugs.

Therefore I started to write the new client fexit in Python.
Here we are :-)


> > This is only one of the tasks. The main menu looks:
> >
> > [s] send a file or directory
> > [g] get a file
> > [c] change login data (user, server, auth-ID)
> > [l] login with webbrowser
> > [u] update fexit
> > [h] help
> > [q] quit
>
> All of this is easily integrated into a GUI like the one I posted (have
> you tried it?)

As I wrote: I have done this already with Perl/Tk and it was HASSLE.
No fun at all.


> IMO the most common GUI pattern for this kind of thing is a side-by-side
> view of the directories on the server and on the client

There is no directory view on server side.


> For an experienced GUI script writer it'll take a weekend to get the
> basics running.

I am not even a beginner GUI script writer and I do not want to become one.
GUIs are most superfluous and delay the work flow.


> for guided user input, an interface which prompts the user for input has
> never been a good solution. You have to work very hard to make that
> convenient.

This is easy, because they have no alternative :-)


> Have a look at lftp, for instance.

Yes. Horrible user interface and even more horrible to program :-}


> A (still) alternative solution would be an interface to the OS to make
> it a remote mounted folder

There are no remote folders.


> (works for WebDAV on any modern OS, for instance) or a daemon, which
> watches and synchronizes a directory (this is how Dropbox works).

A VERY bad idea, if you have to send TB files.


> This way it feels much more integrated to the user

It shall not look integrated. The user should think before using it.


> they can use whatever file manager they like to do the transfer

There are no file manager which supports the F*EX protocol.
Therefore I am forced to write my own clients.
I am a lazy guy: if there is already a program, I will happily use it.
Only if there is none, I program it by myself.


> or even "save" from any application (like Word, Firefox, ...) into the
> remote folder.

There are no remote folders.

Ulli Horlacher

unread,
Dec 10, 2015, 3:28:50 AM12/10/15
to
Ulli Horlacher <fram...@rus.uni-stuttgart.de> wrote:

> > But... is there a windows program with which one can select files and the
> > result is written to STDOUT?
>
> Found it:
>
> from Tkinter import Tk
> from tkFileDialog import askopenfilename
>
> Tk().withdraw()
> file = askopenfilename()

My users do not like it :-(
They want to drag&drop files.
Therefore I have added it as another option to enter files:

[f] select a file
[d] select a directory
[e] enter a file or directory (with drag&drop or copy&paste)

With [f] starts askopenfilename and [d] starts askdirectory

The problem with [e] is: my users do not press ENTER after pasting.

My idea now is: instead of raw_input() I use a get_paste() function, which
reads input character for input character and after a (say) 1 s timeout it
returns the string. Pasting a string with the mouse is rather fast, there
should be no big delay between the characters.

How can I implement such a get_paste() function?
I need a non-blocking getkey() function.

It must work on Windows and Linux.


Christian Gollwitzer

unread,
Dec 10, 2015, 3:54:40 AM12/10/15
to
Am 10.12.15 um 09:28 schrieb Ulli Horlacher:
> Ulli Horlacher <fram...@rus.uni-stuttgart.de> wrote:
>> Found it:
>>
>> from Tkinter import Tk
>> from tkFileDialog import askopenfilename
>>
>> Tk().withdraw()
>> file = askopenfilename()
>
> My users do not like it :-(
> They want to drag&drop files.
> Therefore I have added it as another option to enter files:
>
> [f] select a file
> [d] select a directory
> [e] enter a file or directory (with drag&drop or copy&paste)


Well I know that you won't take my advice but.....

There are standard protocols for drag'n'drop of files and folders on all
three major platforms. Tk supports this using the optional TkDND module,
which unfortunately isn't installed with a standard Python distribution.
Beware there is a "Tkdnd" Python module which implements local
Drag'n'drop only; you need the "real thing" from here

http://sourceforge.net/projects/tkdnd/

plus the correct Python bindings: Maybe this is the correct one:
http://osdir.com/ml/python.tkinter/2005-07/msg00000.html
I'm not sure - never used it from Python, only from Tcl. Using "the real
thing" also allows you to accept multiple files/drectories dragged from
the system file manager. Of course, you need a Tk main window to
implement this, which you refused earlier.

> With [f] starts askopenfilename and [d] starts askdirectory
>
> The problem with [e] is: my users do not press ENTER after pasting.
>
> My idea now is: instead of raw_input() I use a get_paste() function, which
> reads input character for input character and after a (say) 1 s timeout it
> returns the string. Pasting a string with the mouse is rather fast, there
> should be no big delay between the characters.
>
> How can I implement such a get_paste() function?
> I need a non-blocking getkey() function.
>
> It must work on Windows and Linux.

Raw tty input. You'll have to write two different versions for Windows
and Linux. Sorry I can't help with that one.

Christian

Christian Gollwitzer

unread,
Dec 10, 2015, 3:57:40 AM12/10/15
to
Am 10.12.15 um 09:28 schrieb Ulli Horlacher:
> Ulli Horlacher <fram...@rus.uni-stuttgart.de> wrote:
> My users do not like it :-(
> They want to drag&drop files.

Another cheap solution comes to mind: On windows, dropping files onto an
icon on the desktop is interpreted as "launch the program with
additional arguments", where the arguments are the file names. Maybe you
could try interpreting the cmdline args first? I'm not so sure how it
will work with non-ASCII characters, though. On Linux, you can probably
also create simliar icons. The only drawback is that you start a new
instance of your file manager each time.

Christian

Ulli Horlacher

unread,
Dec 10, 2015, 5:26:24 AM12/10/15
to
Christian Gollwitzer <auri...@gmx.de> wrote:

> > My users do not like it :-(
> > They want to drag&drop files.
> > Therefore I have added it as another option to enter files:
> >
> > [f] select a file
> > [d] select a directory
> > [e] enter a file or directory (with drag&drop or copy&paste)
>
>
> Well I know that you won't take my advice but.....
>
> There are standard protocols for drag'n'drop of files and folders on all
> three major platforms. Tk supports this using the optional TkDND module,
> which unfortunately isn't installed with a standard Python distribution.

Then this is no-go.
My users cannot install any additional software.

Ulli Horlacher

unread,
Dec 10, 2015, 5:41:10 AM12/10/15
to
Christian Gollwitzer <auri...@gmx.de> wrote:

> Another cheap solution comes to mind: On windows, dropping files onto an
> icon on the desktop is interpreted as "launch the program with
> additional arguments", where the arguments are the file names.

Ohhh... great! This helps me a lot!


> Maybe you could try interpreting the cmdline args first?

I have implemented this since the beginning of the project :-)


> I'm not so sure how it will work with non-ASCII characters,

My users have to test it. I do not have non-ASCII filenames.

Ulli Horlacher

unread,
Dec 10, 2015, 10:52:29 AM12/10/15
to
Ulli Horlacher <fram...@rus.uni-stuttgart.de> wrote:

> My idea now is: instead of raw_input() I use a get_paste() function, which
> reads input character for input character and after a (say) 1 s timeout it
> returns the string. Pasting a string with the mouse is rather fast, there
> should be no big delay between the characters.
>
> How can I implement such a get_paste() function?
> I need a non-blocking getkey() function.

I found a solution for Windows:

print("\nCopy&paste a filename or drag&drop a file into this window")
file = get_paste()
print('\n"%s"' % file)


def get_paste():
import msvcrt
c = msvcrt.getch()
if c == '\n' or c == '\r': return ''
paste = c
while msvcrt.kbhit():
c = msvcrt.getch()
if c == '\n' or c == '\r': break
paste += c
return paste
0 new messages