назначить конкретное значение Perl STDIN

Как показали другие, чтение 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: проблема с скоростью

0
задан user2831586 3 March 2019 в 16:09
поделиться

1 ответ

Согласно perldoc open :

[...] вы можете открывать файловые дескрипторы непосредственно в скалярах Perl с помощью:

open(my $fh, ">", \$variable) || ..   
[ 1127], см. Также PerlIO :: scalar . Далее, в соответствии с perldoc perlop :

Нулевой дескриптор файла <> является специальным: его можно использовать для эмуляции поведения 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;
}
0
ответ дан Håkon Hægland 3 March 2019 в 16:09
поделиться
Другие вопросы по тегам:

Похожие вопросы: