Да, вы можете! Это называется sshfs.
Основная идея:
Установить sshfssudo apt install sshfs
Установить удаленный каталог sshfs user@host:/path/to/remote /path/to/local/mount/point
Теперь у вас есть пульт дистанционного управления каталог /path/to/remote доступен в /path/to/local/mount/point.
Вот еще один вариант с использованием планировщика ввода-вывода GIO (я никогда раньше не использовал его с Python, но пример ниже, похоже, работает нормально).
from gi.repository import GLib, Gio, GObject
import time
def slow_stuff(job, cancellable, user_data):
print "Slow!"
for i in xrange(5):
print "doing slow stuff..."
time.sleep(0.5)
print "finished doing slow stuff!"
return False # job completed
def main():
GObject.threads_init()
print "Starting..."
Gio.io_scheduler_push_job(slow_stuff, None, GLib.PRIORITY_DEFAULT, None)
print "It's running async..."
GLib.idle_add(ui_stuff)
GLib.MainLoop().run()
def ui_stuff():
print "This is the UI doing stuff..."
time.sleep(1)
return True
if __name__ == '__main__':
main()
Использовать интроспективный API Gio
для чтения файла с его асинхронными методами и при выполнении начального вызова сделать это как тайм-аут с GLib.timeout_add_seconds(3, call_the_gio_stuff)
, где call_the_gio_stuff
- это функция, которая возвращает False
.
Тайм-аут здесь необходимо добавить (может потребоваться другое количество секунд), так как в то время как асинхронные вызовы Gio являются асинхронными, они не являются неблокирующими, что означает, что активность жесткого диска чтения большой файл или большое количество файлов, может привести к блокированному пользовательскому интерфейсу, поскольку пользовательский интерфейс и ввод-вывод все еще находятся в одном и том же (основном) потоке.
Если вы хотите написать свои собственные функции, async и интегрироваться с основным циклом, используя API-интерфейсы ввода-вывода файлов Python, вам нужно будет написать код в виде GObject или передать обратные вызовы или использовать python-defer
, чтобы помочь вам это сделать. Но лучше использовать Gio здесь, так как он может принести вам массу приятных функций, особенно если вы делаете файл открытым / сохраненным в UX.
Вы также можете использовать GLib.idle_add (обратный вызов) для вызова долговременной задачи, когда GLib Mainloop завершает все события с более высоким приоритетом (которые, я считаю, включает в себя создание пользовательского интерфейса).
Я думаю, что это означает, что это сложный способ сделать то, что предложил @mhall.
По сути, у вас есть запуск, затем запустите эту функцию async_call.
Если вы хотите посмотреть, как это работает, вы можете играть с таймером сна и продолжать нажимать кнопку. [Gg]
Исходя из этого , который не является моей работой.
import threading
import time
from gi.repository import Gtk, GObject
# calls f on another thread
def async_call(f, on_done):
if not on_done:
on_done = lambda r, e: None
def do_call():
result = None
error = None
try:
result = f()
except Exception, err:
error = err
GObject.idle_add(lambda: on_done(result, error))
thread = threading.Thread(target = do_call)
thread.start()
class SlowLoad(Gtk.Window):
def __init__(self):
Gtk.Window.__init__(self, title="Hello World")
GObject.threads_init()
self.connect("delete-event", Gtk.main_quit)
self.button = Gtk.Button(label="Click Here")
self.button.connect("clicked", self.on_button_clicked)
self.add(self.button)
self.file_contents = 'Slow load pending'
async_call(self.slow_load, self.slow_complete)
def on_button_clicked(self, widget):
print self.file_contents
def slow_complete(self, results, errors):
'''
'''
self.file_contents = results
self.button.set_label(self.file_contents)
self.button.show_all()
def slow_load(self):
'''
'''
time.sleep(5)
self.file_contents = "Slow load in progress..."
time.sleep(5)
return 'Slow load complete'
if __name__ == '__main__':
win = SlowLoad()
win.show_all()
#time.sleep(10)
Gtk.main()
Дополнительно, вы должны допустить, чтобы другой поток завершился до того, как он завершится правильно или проверьте файл file.lock в дочернем потоке.
Редактировать комментарий к адресу: Первоначально я забыл GObject.threads_init()
. Очевидно, когда кнопка срабатывала, для меня была инициализирована резьба. Это замаскировало ошибку для меня.
Обычно поток создает окно в памяти, сразу же запускает другой поток, когда поток завершает обновление кнопки. Я добавил дополнительный сон, прежде чем я даже позвонил в Gtk.main, чтобы убедиться, что полное обновление COULD запустилось до того, как окно было даже рисовано. Я также прокомментировал это, чтобы убедиться, что запуск потока не мешает рисованию окна.
Вот еще один вариант с использованием планировщика ввода-вывода GIO (я никогда раньше не использовал его с Python, но пример ниже выглядит нормально).
from gi.repository import GLib, Gio, GObject
import time
def slow_stuff(job, cancellable, user_data):
print "Slow!"
for i in xrange(5):
print "doing slow stuff..."
time.sleep(0.5)
print "finished doing slow stuff!"
return False # job completed
def main():
GObject.threads_init()
print "Starting..."
Gio.io_scheduler_push_job(slow_stuff, None, GLib.PRIORITY_DEFAULT, None)
print "It's running async..."
GLib.idle_add(ui_stuff)
GLib.MainLoop().run()
def ui_stuff():
print "This is the UI doing stuff..."
time.sleep(1)
return True
if __name__ == '__main__':
main()
Вы также можете использовать GLib.idle_add (обратный вызов) для вызова долговременной задачи, когда GLib Mainloop завершает все события с более высоким приоритетом (которые, я считаю, включает в себя создание пользовательского интерфейса).
idle_add
заключается в том, что возвращаемое значение обратного вызова имеет значение. Если это правда, оно будет вызвано снова.
– Flimm
19 April 2013 в 00:20
Я думаю, что это означает, что это сложный способ сделать то, что предложил @mhall.
По сути, у вас есть запуск, затем запустите эту функцию async_call.
Если вы хотите посмотреть, как это работает, вы можете играть с таймером сна и продолжать нажимать кнопку. [Gg]
Исходя из этого , который не является моей работой.
import threading
import time
from gi.repository import Gtk, GObject
# calls f on another thread
def async_call(f, on_done):
if not on_done:
on_done = lambda r, e: None
def do_call():
result = None
error = None
try:
result = f()
except Exception, err:
error = err
GObject.idle_add(lambda: on_done(result, error))
thread = threading.Thread(target = do_call)
thread.start()
class SlowLoad(Gtk.Window):
def __init__(self):
Gtk.Window.__init__(self, title="Hello World")
GObject.threads_init()
self.connect("delete-event", Gtk.main_quit)
self.button = Gtk.Button(label="Click Here")
self.button.connect("clicked", self.on_button_clicked)
self.add(self.button)
self.file_contents = 'Slow load pending'
async_call(self.slow_load, self.slow_complete)
def on_button_clicked(self, widget):
print self.file_contents
def slow_complete(self, results, errors):
'''
'''
self.file_contents = results
self.button.set_label(self.file_contents)
self.button.show_all()
def slow_load(self):
'''
'''
time.sleep(5)
self.file_contents = "Slow load in progress..."
time.sleep(5)
return 'Slow load complete'
if __name__ == '__main__':
win = SlowLoad()
win.show_all()
#time.sleep(10)
Gtk.main()
Дополнительно, вы должны допустить, чтобы другой поток завершился до того, как он завершится правильно или проверьте файл file.lock в дочернем потоке.
Редактировать комментарий к адресу: Первоначально я забыл GObject.threads_init()
. Очевидно, когда кнопка срабатывала, для меня была инициализирована резьба. Это замаскировало ошибку для меня.
Обычно поток создает окно в памяти, сразу же запускает другой поток, когда поток завершает обновление кнопки. Я добавил дополнительный сон, прежде чем я даже позвонил в Gtk.main, чтобы убедиться, что полное обновление COULD запустилось до того, как окно было даже рисовано. Я также прокомментировал это, чтобы убедиться, что запуск потока не мешает рисованию окна.
slow_load
будет запущен вскоре после запуска пользовательского интерфейса, но он, кажется, никогда не будет вызван, если не нажать кнопку, что меня немного смущает, поскольку я думал, что цель кнопки была просто обеспечить визуальную индикацию состояния задачи.
– David Planella
27 May 2012 в 20:57
async_call
в этом примере работает для меня, но он приносит хаос, когда я переношу его в свое приложение, и добавляю реальную функцию slow_load
, которая у меня есть.
– David Planella
28 May 2012 в 04:09
Вот еще один вариант с использованием планировщика ввода-вывода GIO (я никогда раньше не использовал его с Python, но пример ниже, похоже, работает нормально).
from gi.repository import GLib, Gio, GObject
import time
def slow_stuff(job, cancellable, user_data):
print "Slow!"
for i in xrange(5):
print "doing slow stuff..."
time.sleep(0.5)
print "finished doing slow stuff!"
return False # job completed
def main():
GObject.threads_init()
print "Starting..."
Gio.io_scheduler_push_job(slow_stuff, None, GLib.PRIORITY_DEFAULT, None)
print "It's running async..."
GLib.idle_add(ui_stuff)
GLib.MainLoop().run()
def ui_stuff():
print "This is the UI doing stuff..."
time.sleep(1)
return True
if __name__ == '__main__':
main()