如何从PHP内部传递和接收参数运行Ruby / Python脚本? [英] How to run Ruby/Python scripts from inside PHP passing and receiving parameters?

查看:94
本文介绍了如何从PHP内部传递和接收参数运行Ruby / Python脚本?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我需要将HTML变成相当于Markdown结构的文本。

OBS .: 使用PHP& Python



当我使用PHP编程时,有些人表示 Markdownify 来完成这项工作,但不幸的是,代码是没有被更新,事实上它没有工作。在sourceforge.net/projects/markdownify有一个注意:不支持 - 你想维护这个项目吗?与我联系!Markdownify是一个用PHP编写的HTML到Markdown转换器。将它看作是html2text.php的继承者,因为它具有更好的设计,更好的表现和更少的角落案例。



从我能发现的情况来看,我只有两个不错的选择:
$ b $ Ruby:Singpolyma的html2markdown.rb,基于Nokogiri / b>


因此,从PHP开始,我需要传递HTML代码,调用Ruby / Python脚本并接收输出。(顺便说一句,一个民间人在这里提出了一个类似的问题(如何从php调用ruby脚本?),但没有给我实例提供实际的信息)。

继Tin Man的小费(波纹管)之后,我得到了这个结论: b
$ b

PHP代码:

  $ t ='< p>< b>您好< b>< i>世界!< / i> ;< / p为H.; 
$ scaped = preg_quote($ t,/);
$ program ='python html2md.py';

// exec($ program。''。$ scaped,$ n);的print_r($ N);出口; //作品!!!

$ input = $ t;

$ descriptorspec = array(
array('pipe','r'),// stdin是一个孩子读取的管道$ b $ array('pipe', 'w'),// stdout是孩子写入
数组('file','。/ error-output.txt','a')的管道// stderr是要写入的文件
);

$ process = proc_open($ program,$ descriptorspec,$ pipes);

if(is_resource($ process)){
fwrite($ pipes [0],$ input);
fclose($ pipes [0]);
$ r = stream_get_contents($ pipes [1]);
fclose($ pipes [1]);
$ return_value = proc_close($ process);
echo命令返回$ return_value \\\
;
print_r($ pipes);
print_r($ r);

Python代码:

 #! / usr / bin / env python 
import html2text
import sys
print html2text.html2text(sys.argv [1])$ ​​b $ b #printHi! #作品!!!

通过上面的介绍,我可以这样做:



命令返回1
数组

[0] =>资源ID#17
1 =>资源ID#18



以及error-output.txt文件说:

追溯(最近一次调用最后一次):
文件html2md.py,第5行,在
print html2text.html2text(sys.argv 1
IndexError:列表索引超出范围



任何想法




Ruby代码( still beeing分析

 #!/ usr / bin / env ruby​​ 
require_relative'html2markdown'
将HTML2Markdown.new(< h1>#{ARGF.read}< / h1>)放入_b $ b






为了记录,我尝试过使用PHP最简单的exec(),但是我遇到了一些有特殊字符的问题非常适用于HTML语言。



PHP代码:

  echo exec ( './hi.rb'); 
echo exec('./ hi.py');

Ruby代码:

 #!/ usr / bin / ruby​​ 
放入Hello World!

Python代码:

 #!usr / bin / python 
import sys
print sys.argv [1]

两者都正常工作。但是,当字符串有点复杂时:

  $ h ='< p>< b> Hello< / b> ;< I>!世界< / I>< / p为H.'; 
echo exec(python hi.py $ h);

完全没有用。



这是因为html字符串需要对其特殊字符进行扫描。我使用了它:

  $ t ='< p>< b> Hello< / b>< i> ;!世界< / I>< / p为H.'; 
$ scaped = preg_quote($ t,/);

现在它就像我说的这里



我是runnig:
Fedora 14
ruby​​ 1.8.7
Python 2.7
perl 5.12.2
PHP 5.3.4
nginx 0.8.53

解决方案

让PHP通过 proc_open ,将HTML管道输入到STDIN中脚本。 Ruby / Python脚本读取并处理数据,并通过STDOUT将其返回到PHP脚本,然后退出。这是一种通过Perl,Ruby或Python中的类似功能执行事务的常用方式,并且非常好,因为它可以让您访问STDERR,以防万一出现问题, t需要临时文件,但要复杂一点。



另外一种方法是将数据从PHP写入临时文件,然后使用 system exec 或其他类似于调用Ruby / Python脚本来打开并处理它,并使用STDOUT打印输出。

编辑:

请参阅 @ Jonke的回答Ruby中使用STDIN的最佳做法?例如读取STDIN和使用Ruby写入STDOUT是多么简单。 你如何从Python中的stdin中读取有一些该语言的良好示例。



这是一个简单的例子,显示如何调用Ruby脚本,通过PHP的STDIN管道将字符串传递给它,并阅读Ruby脚本的STDOUT:

<保存为test.php:

 <?php 
$ descriptorspec = array(
0 => array(pipe,r),// stdin是孩子读取的管道
1 => array(pipe,w),// stdout是孩子写入
2 =>数组(file,./error-output.txt,a)的管道// stderr是写入$ b $的文件b);
$ process = proc_open('ruby ./test.rb',$ descriptorspec,$ pipes);

if(is_resource($ process)){
// $ pipes现在看起来像这样:
// 0 =>可写入的句柄连接到子标准
// 1 =>可读的句柄连接到子标准输出
//任何错误输出将被附加到/tmp/error-output.txt

fwrite($ pipes [0],'hello world');
fclose($ pipes [0]);

echo stream_get_contents($ pipes [1]);
fclose($ pipes [1]);

//在调用
// proc_close之前关闭任何管道以避免死锁非常重要
$ return_value = proc_close($ process);

echocommand returned $ return_value \\\
;
}
?>

另存为test.rb:

 #!/ usr / bin / env ruby​​ 

puts< b>#{ARGF.read}< / b>

运行PHP脚本给出:

  Greg:桌面greg $ php test.php 
< b> hello world< / b>
命令返回0

PHP脚本打开打开Ruby脚本的Ruby解释器。然后PHP发送hello world给它。 Ruby将接收到的文本以粗体标记包装,并将其输出,并由PHP捕获,然后输出。没有临时文件,在命令行上没有任何东西传递,如果需要的话可以传递大量数据,而且速度非常快。 Python或Perl很容易被用来代替Ruby。



编辑:



如果你有:

  HTML2Markdown.new('< h1> HTMLcode< / h1>).to_s 



作为示例代码,那么您可以开始开发Ruby解决方案:

 #!/ usr / bin / env ruby​​ 

require_relative'html2markdown'

放置HTML2Markdown.new(< h1>#{ARGF.read假设你已经下载了HTML2Markdown代码并且拥有这些代码,那么你就可以使用它来创建一个新的HTML代码。它在当前目录中并且正在运行Ruby 1.9.2。


I need to turn HTML into equivalent Markdown-structured text.

OBS.: Quick and clear way of doing this with PHP & Python.

As I am programming in PHP, some people indicates Markdownify to do the job, but unfortunately, the code is not being updated and in fact it is not working. At sourceforge.net/projects/markdownify there is a "NOTE: unsupported - do you want to maintain this project? contact me! Markdownify is a HTML to Markdown converter written in PHP. See it as the successor to html2text.php since it has better design, better performance and less corner cases."

From what I could discover, I have only two good choices:

  • Python: Aaron Swartz's html2text.py

  • Ruby: Singpolyma's html2markdown.rb, based on Nokogiri

So, from PHP, I need to pass the HTML code, call the Ruby/Python Script and receive the output back.

(By the way, a folk made a similar question here ("how to call ruby script from php?") but with no practical information to my case).

Following the Tin Man`s tip (bellow), I got to this:

PHP code:

$t='<p><b>Hello</b><i>world!</i></p>';
$scaped=preg_quote($t,"/");
$program='python html2md.py';

//exec($program.' '.$scaped,$n); print_r($n); exit; //Works!!!

$input=$t;

$descriptorspec=array(
   array('pipe','r'),//stdin is a pipe that the child will read from
   array('pipe','w'),//stdout is a pipe that the child will write to
   array('file','./error-output.txt','a')//stderr is a file to write to
);

$process=proc_open($program,$descriptorspec,$pipes);

if(is_resource($process)){
    fwrite($pipes[0],$input);
    fclose($pipes[0]);
    $r=stream_get_contents($pipes[1]);
    fclose($pipes[1]);
    $return_value=proc_close($process);
    echo "command returned $return_value\n";
    print_r($pipes);
    print_r($r);
}

Python code:

#! /usr/bin/env python
import html2text
import sys
print html2text.html2text(sys.argv[1])
#print "Hi!" #works!!!

With the above I am geting this:

command returned 1 Array ( [0] => Resource id #17 1 => Resource id #18 )

And the "error-output.txt" file says:

Traceback (most recent call last): File "html2md.py", line 5, in print html2text.html2text(sys.argv1) IndexError: list index out of range

Any ideas???


Ruby code (still beeing analysed)

#!/usr/bin/env ruby
require_relative 'html2markdown'
puts HTML2Markdown.new("<h1>#{ ARGF.read }</h1>").to_s


Just for the records, I tryed before to use PHP's most simple "exec()" but I got some problemas with some special characters very common to HTML language.

PHP code:

echo exec('./hi.rb');
echo exec('./hi.py');

Ruby code:

#!/usr/bin/ruby
puts "Hello World!"

Python code:

#!usr/bin/python
import sys
print sys.argv[1]

Both working fine. But when the string is a bit more complicated:

$h='<p><b>Hello</b><i>world!</i></p>';
echo exec("python hi.py $h");

It did not work at all.

That's because the html string needed to have its special characters scaped. I got it using this:

$t='<p><b>Hello</b><i>world!</i></p>';
$scaped=preg_quote($t,"/");

Now it works like I said here.

I am runnig: Fedora 14 ruby 1.8.7 Python 2.7 perl 5.12.2 PHP 5.3.4 nginx 0.8.53

解决方案

Have PHP open the Ruby or Python script via proc_open, piping the HTML into STDIN in the script. The Ruby/Python script reads and processes the data and returns it via STDOUT back to the PHP script, then exits. This is a common way of doing things via popen-like functionality in Perl, Ruby or Python and is nice because it gives you access to STDERR in case something blows chunks and doesn't require temp files, but it's a bit more complex.

Alternate ways of doing it could be writing the data from PHP to a temporary file, then using system, exec, or something similar to call the Ruby/Python script to open and process it, and print the output using their STDOUT.

EDIT:

See @Jonke's answer for "Best practices with STDIN in Ruby?" for examples of how simple it is to read STDIN and write to STDOUT with Ruby. "How do you read from stdin in python" has some good samples for that language.

This is a simple example showing how to call a Ruby script, passing a string to it via PHP's STDIN pipe, and reading the Ruby script's STDOUT:

Save this as "test.php":

<?php
$descriptorspec = array(
   0 => array("pipe", "r"),  // stdin is a pipe that the child will read from
   1 => array("pipe", "w"),  // stdout is a pipe that the child will write to
   2 => array("file", "./error-output.txt", "a") // stderr is a file to write to
);
$process = proc_open('ruby ./test.rb', $descriptorspec, $pipes);

if (is_resource($process)) {
    // $pipes now looks like this:
    // 0 => writeable handle connected to child stdin
    // 1 => readable handle connected to child stdout
    // Any error output will be appended to /tmp/error-output.txt

    fwrite($pipes[0], 'hello world');
    fclose($pipes[0]);

    echo stream_get_contents($pipes[1]);
    fclose($pipes[1]);

    // It is important that you close any pipes before calling
    // proc_close in order to avoid a deadlock
    $return_value = proc_close($process);

    echo "command returned $return_value\n";
}
?>

Save this as "test.rb":

#!/usr/bin/env ruby

puts "<b>#{ ARGF.read }</b>"

Running the PHP script gives:

Greg:Desktop greg$ php test.php 
<b>hello world</b>
command returned 0

The PHP script is opening the Ruby interpreter which opens the Ruby script. PHP then sends "hello world" to it. Ruby wraps the received text in bold tags, and outputs it, which is captured by PHP, and then output. There are no temp files, nothing passed on the command-line, you could pass a LOT of data if need-be, and it would be pretty fast. Python or Perl could easily be used instead of Ruby.

EDIT:

If you have:

HTML2Markdown.new('<h1>HTMLcode</h1>').to_s

as sample code, then you could begin developing a Ruby solution with:

#!/usr/bin/env ruby

require_relative 'html2markdown'

puts HTML2Markdown.new("<h1>#{ ARGF.read }</h1>").to_s

assuming you've already downloaded the HTML2Markdown code and have it in the current directory and are running Ruby 1.9.2.

这篇关于如何从PHP内部传递和接收参数运行Ruby / Python脚本?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆