История изменений
Исправление hakavlad, (текущая версия) :
ах! тогда могу предложить безопасное средство копирования:
#!/usr/bin/env python3
"""xcp
usage:
./xcp source dest_file
"""
import os
from time import monotonic, sleep
from sys import argv, exit
import threading
def start_thread(func, *a, **k):
""" run function in a new thread
"""
threading.Thread(target=func, args=a, kwargs=k, daemon=True).start()
fd = dict()
x = dict()
MIB = 1024**2
chunk_size = MIB
fd['FINISH_READER'] = False
if_path, of_path = argv[1:]
if_size0 = os.stat(if_path).st_size
fd['r'] = 0
fd['w'] = 0
try:
fd[if_path] = open(if_path, 'rb')
except Exception as e:
print(e)
exit(1)
try:
fd[of_path] = open(of_path, 'wb')
except Exception as e:
print(e)
exit(1)
print('source file: {}, size: {} MiB'.format(if_path, round(
os.stat(if_path).st_size / MIB, 1)))
print('destination file: {}, size: {} MiB'.format(of_path, round(
os.stat(of_path).st_size / MIB, 1)))
print('-------\n')
t0 = monotonic()
def reader():
"""
"""
c = 0
while True:
if len(x) >= 50:
sleep(0.1)
continue
chunk = fd[if_path].read(chunk_size)
x[c] = chunk
if len(chunk) == 0:
fd['FINISH_READER'] = True
break
c += 1
fd['r'] += len(chunk)
start_thread(reader)
c = 0
while True:
try:
chunk = x[c]
try:
fd[of_path].write(chunk)
except OSError as e:
print(e)
os.fsync(fd[of_path])
exit(1)
del x[c]
os.fsync(fd[of_path])
except KeyError:
sleep(0.1)
continue
c += 1
fd['w'] += len(chunk)
t = monotonic() - t0
speed = fd['w'] / MIB / t
print('\033Mread {}M; written {}M in {}s ({}M/s)'.format(
round(fd['r'] / MIB, 1), round(fd['w'] / MIB, 1), round(t, 1), round(speed, 1)
))
if fd['w'] == fd['r'] and fd['FINISH_READER']:
os.fsync(fd[of_path])
break
t = monotonic() - t0
speed = fd['w'] / MIB / t
print('-------')
print('OK; read {}M; written {}M in {}s ({}M/s)'.format(
round(fd['r'] / MIB, 1), round(fd['w'] / MIB, 1), round(t, 1), round(speed, 1)
))
Вывод примерно такой:
$ ./xcp a b
source file: a, size: 390.5 MiB
destination file: b, size: 0.0 MiB
-------
read 390.5M; written 390.5M in 42.7s (9.1M/s)
-------
OK; read 390.5M; written 390.5M in 42.7s (9.1M/s)
Копирует чанками по мегабайту, выполняет fsync периодически. Прогресс отображает.
Исходная версия hakavlad, :
ах! тогда могу предложить безопасное средство копирования:
#!/usr/bin/env python3
"""xcp
usage:
./xcp source dest_file
"""
import os
from time import monotonic, sleep
from sys import argv, exit
import threading
def start_thread(func, *a, **k):
""" run function in a new thread
"""
threading.Thread(target=func, args=a, kwargs=k, daemon=True).start()
fd = dict()
x = dict()
MIB = 1024**2
chunk_size = MIB
fd['FINISH_READER'] = False
if_path, of_path = argv[1:]
if_size0 = os.stat(if_path).st_size
fd['r'] = 0
fd['w'] = 0
try:
fd[if_path] = open(if_path, 'rb')
except Exception as e:
print(e)
exit(1)
# обнов инфу о размере записанного
try:
fd[of_path] = open(of_path, 'wb')
except Exception as e:
print(e)
exit(1)
print('source file: {}, size: {} MiB'.format(if_path, round(
os.stat(if_path).st_size / MIB, 1)))
print('destination file: {}, size: {} MiB'.format(of_path, round(
os.stat(of_path).st_size / MIB, 1)))
print('-------\n')
t0 = monotonic()
def reader():
"""
"""
c = 0
while True:
if len(x) >= 50:
sleep(0.1)
continue
chunk = fd[if_path].read(chunk_size)
x[c] = chunk
if len(chunk) == 0:
fd['FINISH_READER'] = True
break
c += 1
fd['r'] += len(chunk)
start_thread(reader)
c = 0
while True:
try:
chunk = x[c]
try:
fd[of_path].write(chunk)
except OSError as e:
print(e)
os.fsync(fd[of_path])
exit(1)
del x[c]
os.fsync(fd[of_path])
except KeyError:
sleep(0.1)
continue
c += 1
fd['w'] += len(chunk)
t = monotonic() - t0
speed = fd['w'] / MIB / t
print('\033Mread {}M; written {}M in {}s ({}M/s)'.format(
round(fd['r'] / MIB, 1), round(fd['w'] / MIB, 1), round(t, 1), round(speed, 1)
))
if fd['w'] == fd['r'] and fd['FINISH_READER']:
os.fsync(fd[of_path])
break
t = monotonic() - t0
speed = fd['w'] / MIB / t
print('-------')
print('OK; read {}M; written {}M in {}s ({}M/s)'.format(
round(fd['r'] / MIB, 1), round(fd['w'] / MIB, 1), round(t, 1), round(speed, 1)
))
Вывод примерно такой:
$ ./xcp a b
source file: a, size: 390.5 MiB
destination file: b, size: 0.0 MiB
-------
read 390.5M; written 390.5M in 42.7s (9.1M/s)
-------
OK; read 390.5M; written 390.5M in 42.7s (9.1M/s)
Копирует чанками по мегабайту, выполняет fsync периодически. Прогресс отображает.