Po uruchomieniu mojego kodu z Pyinstallera czytnik tiff działa dobrze. Po zamrożeniu korzystając Pyinstaller uzyskać następujące ostrzeżenie:Plikoinstalator .exe nie może znaleźć modułu _tiffile - ładowanie niektórych skompresowanych obrazów będzie bardzo powolne
UserWarning: ImportError: No module named '_tifffile'. Loading of some compressed images will be very slow. Tifffile.c can be obtained at http://www.lfd.uci.edu/~gohlke
I na pewno wystarczy, plik TIFF, że wykorzystywane do podejmowania sekund, aby załadować do tablicy numpy może teraz podjąć minut.
Oto uproszczona forma mojego kodu, aby skupić się na problemie. Jeśli załadujesz przykładowy plik tiff, taki jak this one, powinien on być ładowany szybko bez problemów.
Jeśli używasz C:\Python35\python.exe C:\Python35\Scripts\pyinstaller.exe --additional-hooks-dir=. --clean --win-private-assemblies tiffile_problems.py
powinieneś uzyskać funkcjonalny plik .exe z powyższym komunikatem o błędzie po uruchomieniu. Kiedy próbujesz załadować ten sam tiff, teraz trwa to znacznie dłużej.
tiffile_problems.py
#!/usr/bin/env python3
import os
import sys
import traceback
import numpy as np
import matplotlib.pyplot as plt
from PyQt4.QtGui import *
from PyQt4.QtCore import *
sys.path.append('..')
from MBE_for_SO.util import fileloader, fileconverter
class NotConvertedError(Exception):
pass
class FileAlreadyInProjectError(Exception):
def __init__(self, filename):
self.filename = filename
class Widget(QWidget):
def __init__(self, project, parent=None):
super(Widget, self).__init__(parent)
if not project:
self.setup_ui()
return
def setup_ui(self):
vbox = QVBoxLayout()
## Related to importing Raws
self.setWindowTitle('Import Raw File')
#vbox.addWidget(QLabel('Set the size all data are to be rescaled to'))
grid = QGridLayout()
vbox.addLayout(grid)
vbox.addStretch()
self.setLayout(vbox)
self.resize(400, 220)
self.listview = QListView()
self.listview.setStyleSheet('QListView::item { height: 26px; }')
self.listview.setSelectionMode(QAbstractItemView.NoSelection)
vbox.addWidget(self.listview)
hbox = QVBoxLayout()
pb = QPushButton('New Video')
pb.clicked.connect(self.new_video)
hbox.addWidget(pb)
vbox.addLayout(hbox)
vbox.addStretch()
self.setLayout(vbox)
def convert_tif(self, filename):
path = os.path.splitext(os.path.basename(filename))[0] + '.npy'
#path = os.path.join(self.project.path, path)
progress = QProgressDialog('Converting tif to npy...', 'Abort', 0, 100, self)
progress.setAutoClose(True)
progress.setMinimumDuration(0)
progress.setValue(0)
def callback(value):
progress.setValue(int(value * 100))
QApplication.processEvents()
try:
fileconverter.tif2npy(filename, path, callback)
print('Tifffile saved to wherever this script is')
except:
# qtutil.critical('Converting tiff to npy failed.')
progress.close()
return path
def to_npy(self, filename):
if filename.endswith('.raw'):
print('No raws allowed')
#filename = self.convert_raw(filename)
elif filename.endswith('.tif'):
filename = self.convert_tif(filename)
else:
raise fileloader.UnknownFileFormatError()
return filename
def import_file(self, filename):
if not filename.endswith('.npy'):
new_filename = self.to_npy(filename)
if not new_filename:
raise NotConvertedError()
else:
filename = new_filename
return filename
def import_files(self, filenames):
for filename in filenames:
try:
filename = self.import_file(filename)
except NotConvertedError:
# qtutil.warning('Skipping file \'{}\' since not converted.'.format(filename))
print('Skipping file \'{}\' since not converted.'.format(filename))
except FileAlreadyInProjectError as e:
# qtutil.warning('Skipping file \'{}\' since already in project.'.format(e.filename))
print('Skipping file \'{}\' since already in project.'.format(e.filename))
except:
# qtutil.critical('Import of \'{}\' failed:\n'.format(filename) +\
# traceback.format_exc())
print('Import of \'{}\' failed:\n'.format(filename) + traceback.format_exc())
# else:
# self.listview.model().appendRow(QStandardItem(filename))
def new_video(self):
filenames = QFileDialog.getOpenFileNames(
self, 'Load images', QSettings().value('last_load_data_path'),
'Video files (*.npy *.tif *.raw)')
if not filenames:
return
QSettings().setValue('last_load_data_path', os.path.dirname(filenames[0]))
self.import_files(filenames)
class MyPlugin:
def __init__(self, project):
self.name = 'Import video files'
self.widget = Widget(project)
def run(self):
pass
if __name__ == '__main__':
app = QApplication(sys.argv)
app.aboutToQuit.connect(app.deleteLater)
w = QMainWindow()
w.setCentralWidget(Widget(None))
w.show()
app.exec_()
sys.exit()
fileconverter.py
#!/usr/bin/env python3
import os
import numpy as np
import tifffile as tiff
class ConvertError(Exception):
pass
def tif2npy(filename_from, filename_to, progress_callback):
with tiff.TiffFile(filename_from) as tif:
w, h = tif[0].shape
shape = len(tif), w, h
np.save(filename_to, np.empty(shape, tif[0].dtype))
fp = np.load(filename_to, mmap_mode='r+')
for i, page in enumerate(tif):
progress_callback(i/float(shape[0]-1))
fp[i] = page.asarray()
def raw2npy(filename_from, filename_to, dtype, width, height,
num_channels, channel, progress_callback):
fp = np.memmap(filename_from, dtype, 'r')
frame_size = width * height * num_channels
if len(fp) % frame_size:
raise ConvertError()
num_frames = len(fp)/frame_size
fp = np.memmap(filename_from, dtype, 'r',
shape=(num_frames, width, height, num_channels))
np.save(filename_to, np.empty((num_frames, width, height), dtype))
fp_to = np.load(filename_to, mmap_mode='r+')
for i, frame in enumerate(fp):
progress_callback(i/float(len(fp)-1))
fp_to[i] = frame[:,:,channel-1]
fileloader.py
#!/usr/bin/env python3
import numpy as np
class UnknownFileFormatError(Exception):
pass
def load_npy(filename):
frames = np.load(filename)
# frames[np.isnan(frames)] = 0
return frames
def load_file(filename):
if filename.endswith('.npy'):
frames = load_npy(filename)
else:
raise UnknownFileFormatError()
return frames
def load_reference_frame_npy(filename, offset):
frames_mmap = np.load(filename, mmap_mode='c')
if frames_mmap is None:
return None
frame = np.array(frames_mmap[offset])
frame[np.isnan(frame)] = 0
frame = frame.swapaxes(0, 1)
if frame.ndim == 2:
frame = frame[:, ::-1]
elif frame.ndim == 3:
frame = frame[:, ::-1, :]
return frame
def load_reference_frame(filename, offset=0):
if filename.endswith('.npy'):
frame = load_reference_frame_npy(filename, offset)
else:
raise UnknownFileFormatError()
return frame
Czemu? I jak to naprawić? Zlokalizowałem tifffile.py, tifffile.cpython-35.pyc, tifffile.c
i umieściłem je wszystkie w tym samym katalogu, co .exe. Bez efektu. _tifffile.cp35-win_amd64.pyd
jest tworzony przez Pyinstaller i umieszczany w tym samym katalogu, co .exe. Nie wiem, jakie inne opcje są dla mnie dostępne.
tifffile_problems.spec
# -*- mode: python -*-
block_cipher = None
a = Analysis(['tiffile_problems.py'],
pathex=['C:\\Users\\Cornelis\\PycharmProjects\\tester\\MBE_for_SO'],
binaries=None,
datas=None,
hiddenimports=[],
hookspath=[],
runtime_hooks=[],
excludes=[],
win_no_prefer_redirects=False,
win_private_assemblies=True,
cipher=block_cipher)
pyz = PYZ(a.pure, a.zipped_data,
cipher=block_cipher)
exe = EXE(pyz,
a.scripts,
exclude_binaries=True,
name='tiffile_problems',
debug=False,
strip=False,
upx=True,
console=True)
coll = COLLECT(exe,
a.binaries,
a.zipfiles,
a.datas,
strip=False,
upx=True,
name='tiffile_problems')
tiffile.spec podczas korzystania C:\Python35\python.exe C:\Python35\Scripts\pyinstaller.exe --additional-hooks-dir=. --clean --win-private-assemblies --onefile tiffile_problems.py
# -*- mode: python -*-
block_cipher = None
a = Analysis(['tiffile_problems.py'],
pathex=['C:\\Users\\Cornelis\\PycharmProjects\\tester\\MBE_for_SO'],
binaries=None,
datas=None,
hiddenimports=[],
hookspath=['.'],
runtime_hooks=[],
excludes=[],
win_no_prefer_redirects=False,
win_private_assemblies=True,
cipher=block_cipher)
pyz = PYZ(a.pure, a.zipped_data,
cipher=block_cipher)
exe = EXE(pyz,
a.scripts,
a.binaries,
a.zipfiles,
a.datas,
name='tiffile_problems',
debug=False,
strip=False,
upx=True,
console=True)
Nie mam żadnych problemów z moim kodem przed zamrożeniem. Pliki Tiff ładują się ładnie i szybko. _tifffile.cp35-win_amd64.pyd jest tworzony przez Pyinstaller i mogę go znaleźć w katalogu, który zawiera .exe. Przeczytałem twój link, ale nie jestem pewien, jak dołączyć _tifffile.cp35-win_amd64.pyd do .spec. Dodałem moje .spec do pytania – Frikster
Próbowałem umieścić datas = [('_tifffile.cp35-win_amd64.pyd ")] jako pole w specyfikacji w Analizie. Ale kiedy uruchamiam program antywirusowy, zauważam, że specyfikacja powraca do stanu wyjściowego. – Frikster
ok nvm Udało mi się zmodyfikować specyfikację, aby dołączyć plik .pyd. Ale nie robi to żadnej różnicy, jak powinienem się spodziewać, ponieważ plik jest już umieszczony w katalogu zawierającym domyślnie .exe. To naturalnie sprawia, że zastanawiam się, co się dzieje? Jeśli plik .c jest już skompilowany i właśnie tam jest, dlaczego nie jest importowany z importem _tifffile? – Frikster