Как показали другие, чтение csv происходит быстрее. Поэтому, если вы находитесь в Windows и имеете Excel, вы можете вызвать vbscript для преобразования Excel в csv, а затем прочитать csv. Я попробовал скрипт ниже, и потребовалось около 30 секунд.
# create a list with sheet numbers you want to process
sheets = map(str,range(1,6))
# convert each sheet to csv and then read it using read_csv
df={}
from subprocess import call
excel='C:\\Users\\rsignell\\OTT_Data_All_stations.xlsx'
for sheet in sheets:
csv = 'C:\\Users\\rsignell\\test' + sheet + '.csv'
call(['cscript.exe', 'C:\\Users\\rsignell\\ExcelToCsv.vbs', excel, csv, sheet])
df[sheet]=pd.read_csv(csv)
Вот небольшой фрагмент питона для создания сценария ExcelToCsv.vbs:
#write vbscript to file
vbscript="""if WScript.Arguments.Count < 3 Then
WScript.Echo "Please specify the source and the destination files. Usage: ExcelToCsv "
Wscript.Quit
End If
csv_format = 6
Set objFSO = CreateObject("Scripting.FileSystemObject")
src_file = objFSO.GetAbsolutePathName(Wscript.Arguments.Item(0))
dest_file = objFSO.GetAbsolutePathName(WScript.Arguments.Item(1))
worksheet_number = CInt(WScript.Arguments.Item(2))
Dim oExcel
Set oExcel = CreateObject("Excel.Application")
Dim oBook
Set oBook = oExcel.Workbooks.Open(src_file)
oBook.Worksheets(worksheet_number).Activate
oBook.SaveAs dest_file, csv_format
oBook.Close False
oExcel.Quit
""";
f = open('ExcelToCsv.vbs','w')
f.write(vbscript.encode('utf-8'))
f.close()
Этот ответ выиграл от Преобразование XLS в CSV в командной строке и csv & amp; Импорт файлов xlsx в кадр данных pandas: проблема с скоростью
Согласно perldoc open
:
[...] вы можете открывать файловые дескрипторы непосредственно в скалярах Perl с помощью:
blockquote> [ 1127], см. Также PerlIO :: scalar . Далее, в соответствии с perldoc perlop :open(my $fh, ">", \$variable) || ..
Нулевой дескриптор файла <> является специальным: его можно использовать для эмуляции поведения
blockquote>sed
иawk
, а также любого другая программа фильтра Unix, которая берет список имен файлов, делая то же самое для каждой строки ввода из всех них. Ввод из<>
поступает либо из стандартного ввода, либо из каждого файла, указанного в командной строке. Вот как это работает: при первом вычислении<>
проверяется массив@ARGV
, и если он пуст, для$ARGV[0]
устанавливается значение"-"
, которое при открытии дает стандартный ввод. Затем массив@ARGV
обрабатывается как список имен файлов.Поэтому, когда вы сделаете
while (<>)
, он попытается «открыть стандартный ввод» (при условии, что вы не указали аргументы командной строки, т. Е.@ARGV
пусто). Эта командаopen
не зависит от текущего значения переменнойSTDIN
, вместо этого (я полагаю) она просто сделает что-то вроде:open ARGV, '/dev/tty' or die "open: /dev/tty: $!";
Так что кажется, что невозможно переопределить поведение
<>
для чтения из строки путем измененияSTDIN
.Но вместо использования нулевого дескриптора файла
<>
в вашем цикле, если вы могли бы вместо этого использовать<STDIN>
... тогда сработало бы переопределениеSTDIN
для дескриптора строкового файла:use strict; use warnings; my $str = "hello\n"; open my $fh, "<", \$str or die "Could not open string file handle: $!"; { local *STDIN = $fh; while (<STDIN>) { print; } } close $fh; my $line = <STDIN>; print "Terminal input: ", $line;
Редактировать :
Следующее также, кажется, работает:
local *ARGV = $fh; while (<>) { print; }