PHP. Загрузите файл, который записывается процессом python [duplicate]

Во-первых, две альтернативы base. Один полагается на table, а другой на ave и length. Затем два пути data.table.


1. table

tt <- table(df$name)

df2 <- subset(df, name %in% names(tt[tt < 3]))
# or
df2 <- df[df$name %in% names(tt[tt < 3]), ]

Если вы хотите шаг за шагом пройти:

# count each 'name', assign result to an object 'tt'
tt <- table(df$name)

# which 'name' in 'tt' occur more than three times?
# Result is a logical vector that can be used to subset the table 'tt'
tt < 3

# from the table, select 'name' that occur < 3 times
tt[tt < 3]

# ...their names
names(tt[tt < 3])

# rows of 'name' in the data frame that matches "the < 3 names"
# the result is a logical vector that can be used to subset the data frame 'df'
df$name %in% names(tt[tt < 3])

# subset data frame by a logical vector
# 'TRUE' rows are kept, 'FALSE' rows are removed.
# assign the result to a data frame with a new name
df2 <- subset(df, name %in% names(tt[tt < 3]))
# or
df2 <- df[df$name %in% names(tt[tt < 3]), ]

2. ave и length

Как предложено @flodel:

df[ave(df$x, df$name, FUN = length) < 3, ]

3. data.table: .N и .SD:

library(data.table)
setDT(df)[, if (.N < 3) .SD, by = name]

4. data.table: .N и .I:

setDT(df)
df[df[, .I[.N < 3], name]$V1] 

См. также соответствующий Q & amp; A Рассчитайте количество наблюдений / строк на группу и добавьте результат в кадр данных .

59
задан Maksim Vi. 15 August 2009 в 05:23
поделиться

10 ответов

Если вы хотите запустить системные команды через PHP, посмотрите документацию exec .

Я бы не рекомендовал делать это на сайте с высоким трафиком, процесс для каждого запроса является довольно сложным процессом. Некоторые программы предоставляют возможность записывать свой идентификатор процесса в файл, который вы могли бы проверить, и завершать процесс по своему усмотрению, но для таких команд, как ping, я не уверен, что это возможно, проверьте страницы man.

Вам может быть лучше обслуживать, просто открыв сокет на порту, который вы ожидаете слушать (IE: порт 80 для HTTP) на удаленном хосте, таким образом вы знаете, что все идет хорошо в пользовательской области, а также на network.

Если вы пытаетесь вывести двоичные данные в функцию заголовка php и убедитесь, что вы задали правильный тип содержимого и Content-Disposition . Просмотрите документацию для получения дополнительной информации об использовании / отключении выходного буфера.

2
ответ дан 2 revs 24 August 2018 в 22:12
поделиться

Я пробовал различные команды выполнения PHP в Windows и обнаружил, что они сильно различаются.

  • Не работает для потоковой передачи: shell_exec, exec, passthru
  • Вид работ: proc_open, popen - «вид», потому что вы не можете передавать аргументы своей команде (т. е. не работать с my.exe --something, будет работать с _my_something.bat).

Наилучший (самый простой) подход:

  1. Вы должны убедиться, что ваш exe - команды промывки (см. проблема с промывкой printf ). Без этого вы, скорее всего, получите партии из примерно 4096 байтов текста, что бы вы ни делали.
  2. Если вы можете, используйте header('Content-Type: text/event-stream'); (вместо header('Content-Type: text/plain; charset=...');). Однако это не будет работать во всех браузерах / клиентах! Потоковая передача будет работать без этого, но по крайней мере первые строки будут буферизованы браузером.
  3. Вы также можете отключить кеш header('Cache-Control: no-cache');.
  4. Отключить буферизацию вывода (либо в php.ini или с помощью ini_set('output_buffering', 'off');). Это также может быть сделано в Apache / Nginx / любом сервере, который вы используете спереди.
  5. Поворот сжатия (либо в php.ini, либо с помощью ini_set('zlib.output_compression', false);). Это также может быть сделано в Apache / Nginx / любом сервере, который вы используете спереди.

Итак, в вашей программе на C ++ вы делаете что-то вроде этого (опять же, для других решений см. printf проблема с промывкой ):

Logger::log(...) {
  printf (text);
  fflush(stdout);
}

В PHP вы делаете что-то вроде:

function setupStreaming() {
    // Turn off output buffering
    ini_set('output_buffering', 'off');
    // Turn off PHP output compression
    ini_set('zlib.output_compression', false);
    // Disable Apache output buffering/compression
    if (function_exists('apache_setenv')) {
        apache_setenv('no-gzip', '1');
        apache_setenv('dont-vary', '1');
    }
}
function runStreamingCommand($cmd){
    echo "\nrunning $cmd\n";
    system($cmd);
}
...

setupStreaming();
runStreamingCommand($cmd);
3
ответ дан Community 24 August 2018 в 22:12
поделиться

почему бы просто не подключить вывод в файл журнала, а затем использовать этот файл для возврата содержимого клиенту. не совсем в режиме реального времени, но, возможно, достаточно хорошо?

0
ответ дан greenone83 24 August 2018 в 22:12
поделиться

Для использования в командной строке:

function execute($cmd) {
    $proc = proc_open($cmd, [['pipe','r'],['pipe','w'],['pipe','w']], $pipes);
    while(($line = fgets($pipes[1])) !== false) {
        fwrite(STDOUT,$line);
    }
    while(($line = fgets($pipes[2])) !== false) {
        fwrite(STDERR,$line);
    }
    fclose($pipes[0]);
    fclose($pipes[1]);
    fclose($pipes[2]);
    return proc_close($proc);
}

Если вы пытаетесь запустить файл, вам может потребоваться сначала предоставить разрешения на выполнение:

chmod('/path/to/script',0755);
2
ответ дан mpen 24 August 2018 в 22:12
поделиться

Это хороший способ показать вывод команд вашей оболочки в реальном времени:

<?php
header("Content-type: text/plain");

// tell php to automatically flush after every output
// including lines of output produced by shell commands
disable_ob();

$command = 'rsync -avz /your/directory1 /your/directory2';
system($command);

Эта функция понадобится для предотвращения буферизации вывода:

function disable_ob() {
    // Turn off output buffering
    ini_set('output_buffering', 'off');
    // Turn off PHP output compression
    ini_set('zlib.output_compression', false);
    // Implicitly flush the buffer(s)
    ini_set('implicit_flush', true);
    ob_implicit_flush(true);
    // Clear, and turn off output buffering
    while (ob_get_level() > 0) {
        // Get the curent level
        $level = ob_get_level();
        // End the buffering
        ob_end_clean();
        // If the current level has not changed, abort
        if (ob_get_level() == $level) break;
    }
    // Disable apache output buffering/compression
    if (function_exists('apache_setenv')) {
        apache_setenv('no-gzip', '1');
        apache_setenv('dont-vary', '1');
    }
}

Это doesn я работаю на каждом сервере, на котором я его пробовал, хотя хотел бы посоветовать, что искать в вашей php-конфигурации, чтобы определить, нужно ли вам вытаскивать волосы, пытаясь заставить этот тип поведения работать на вашем сервер! Кто-нибудь еще знает?

Вот фиктивный пример в простом PHP:

<?php
header("Content-type: text/plain");

disable_ob();

for($i=0;$i<10;$i++) 
{
    echo $i . "\n";
    usleep(300000);
}

Надеюсь, это поможет другим людям, которые отправились туда по пути.

34
ответ дан Petah 24 August 2018 в 22:12
поделиться
  • 1
    Это ничего не делает для меня, на Fedora php 5+ – Doug Molineux 2 January 2012 в 23:55
  • 2
    +1 ... должен использовать proc_close () в конце. – Nathan Lippi 12 June 2012 в 13:13
  • 3
    +1 работает для меня, но только если я добавлю ob_implicit_flush(true);ob_end_flush(); в начале – tetris11 27 September 2012 в 15:15
  • 4
    Объедините это с ответом Робба, и у вас есть зритель. – Petah 8 February 2013 в 00:45
  • 5
    Это не работает с exec(). system() работает нормально. – divinedragon 29 May 2013 в 16:15
  • 6
    Это работало очень хорошо для меня, оно не обновляется постоянно, но все так часто. Лучше, чем ничего. Спасибо. – Exoon 20 December 2013 в 23:58
  • 7
    это создало желаемый эффект для меня на CentOS 6.5 / apache 2.2 / php 5.3. ура! – mxmader 8 April 2014 в 17:53
  • 8
    Я завернул это в функцию, чтобы я мог называть ее так же, как shell_exec. Хорошо работает, если вы просто хотите показать результат и не обрабатывать его. – jxmallett 16 January 2015 в 07:58
  • 9
    Это отлично работает для меня (OS X 10.12, Apache 2.2.3, PHP 7.0.9), но по какой-то причине только тогда, когда также установлен заголовок X-Content-Type-Options: header('X-Content-Type-Options: nosniff'); – Jack Sleight 16 November 2016 в 17:13
  • 10
    Поскольку браузеры обычно ждут некоторого исходного пакета данных, вы можете отправить много пробелов в начале, чтобы начальный буфер был заполнен: for ($i=0; $i < 100000; $i++) { echo " "; } echo "\n"; flush(); – Martin Pecka 11 August 2017 в 09:24

попробуйте это (протестировано на машине Windows + wamp server)

        header('Content-Encoding: none;');

        set_time_limit(0);

        $handle = popen("<<< Your Shell Command >>>", "r");

        if (ob_get_level() == 0) 
            ob_start();

        while(!feof($handle)) {

            $buffer = fgets($handle);
            $buffer = trim(htmlspecialchars($buffer));

            echo $buffer . "<br />";
            echo str_pad('', 4096);    

            ob_flush();
            flush();
            sleep(1);
        }

        pclose($handle);
        ob_end_flush();
5
ответ дан raminious 24 August 2018 в 22:12
поделиться
  • 1
    Этот ответ неверен. Вопрос заключался в том, как получить вывод страницы в реальном времени. С ob_start () вы делаете все наоборот: вы пишете весь вывод во внутренний буфер сервера, а не сразу отправляете его в браузер! – Elmue 26 November 2015 в 14:13
  • 2
    Я пробовал, и он отлично работает на Linux Debian 7. – Rodrigo Balest 15 December 2015 в 11:48
  • 3
    я пробовал ур код, на самом деле его не отображать команду оболочки в режиме реального времени, а просто ждать команды оболочки, чтобы закончить загрузку всего текста и отображение его по биту с помощью справки sleep (1). извините, u заслуживает downvote – Ryan Arief 28 June 2016 в 08:14

Более эффективное решение этой старой проблемы с использованием современных событий на стороне сервера HTML5 описано здесь:

http://www.w3schools.com/html/html5_serversentevents.asp


Пример:

http://sink.agiletoolkit.org/realtime/console

Код: https://github.com/atk4/sink/blob/master/admin/page/realtime/console.php#L40

(Реализовано как модуль в инфраструктуре Agile Toolkit)

5
ответ дан romaninsh 24 August 2018 в 22:12
поделиться

Сначала проверьте, работает ли flush () . Если это так, хорошо, если это не так, вероятно, означает, что веб-сервер по какой-то причине буферизуется, например mod_gzip включен.

Для чего-то вроде ping самым простым методом является цикл внутри PHP, запускать «ping -c 1» несколько раз и вызывать flush () после каждого выхода. Предполагая, что PHP настроен на отмену, когда HTTP-соединение закрывается пользователем (обычно это значение по умолчанию, или вы можете вызвать ignore_user_abort (false), чтобы убедиться), тогда вам не нужно беспокоиться о запущенных процессах ping либо .

Если действительно необходимо, чтобы вы только выполняли дочерний процесс один раз и непрерывно отображали его вывод, что может быть сложнее - вам, вероятно, придется запускать его в фоном, перенаправлять вывод в поток, а затем PHP-эхо-поток, возвращаемый пользователю, чередующийся с регулярными вызовами flush ().

2
ответ дан Todd Owen 24 August 2018 в 22:12
поделиться

Попробуйте изменить набор файлов php.ini «output_buffering = Off». Вы должны иметь возможность получить вывод в реальном времени на странице. Использовать системную команду вместо команды exec .. system будет очищать вывод

0
ответ дан user 24 August 2018 в 22:12
поделиться

Проверено все ответы, ничего не работает ...

Найдено решение Здесь

Он работает на окнах (я думаю, что этот ответ полезен для поиска пользователей там)

<?php
$a = popen('ping www.google.com', 'r'); 

while($b = fgets($a, 2048)) { 
echo $b."<br>\n"; 
ob_flush();flush(); 
} 
pclose($a); 

?>
2
ответ дан ვანი ჩკაა 24 August 2018 в 22:12
поделиться
Другие вопросы по тегам:

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