python CGI无需等待即可调用新的子进程

时间:2018-08-04 22:04:46

标签: python subprocess cgi

我在这里阅读了许多有关在CGI调用的脚本中启动另一个python脚本的问题的文章,即我在启用了CGI的Raspberrypi上运行了apache2服务器。

1)从浏览器:Webform数据被发送到CGI界面,并调用我的python脚本test1.py

2)来自test1.py,我想致电test2.py(它将永远运行或在任何需要的时间运行(它会在某处连续更新值)

3)重点是:我希望CGI脚本立即显示一些结果,例如在“结果网页”上显示“ test2已启动”并在后台运行我的test2.py

但是发生的事情是,带有表单的网页永远等待我的test2.py完成!

我尝试过类似的事情:

p = subprocess.Popen([sys.executable, '/var/www/cgi-bin/test2.py'],
                     stdout=subprocess.PIPE, stderr=subprocess.STDOUT)

但这不起作用(即等待脚本test2完成...)

有人可以帮忙吗?

4 个答案:

答案 0 :(得分:0)


您第一个问题的答案是此链接。getting start Cgi programmin

第二个问题的答案:您应该使用多线程编程。
如果在test2模块中具有示例功能...

    create or replace procedure total_spent(v_fname IN 
    saleinv.cname%TYPE,v_lname IN saleinv.cname%TYPE.v_netspend OUT 
    saleinv.net%TYPE,v_totalpurch OUT NUMBER) AS
    Begin
    select sum(net+tax),count(net) into v_netspend,v_totalpurch from saleinv 
    where cname LIKE '&v_fname%&v_lname';
    END;
    /

    ACCEPT p_fname PROMPT  'Enter The first letter of customer's name' 
    ACCEPT p_lname PROMPT 'Enter the last letter of customer's name'
    BEGIN
    totalspent('&p_fname',&'p_lname');

回答您的第三个问题:
然后,您可以在站点路径中的cgi文件所在的位置创建一个文件夹,或配置某些目录以将某些文件类型作为cgi脚本处理。 上面的apache2文档对此进行了很好的描述,但是实际上,要使cgi文件夹中的所有文件都执行,可以使用以下conf:

        选件ExecCGI         SetHandler CGI脚本     

并允许将.py文件作为脚本在特定文件夹中执行,请使用以下配置文件:

#in test1.py
import threading
import test2
T1 = threading.Thread(test2.sample(object))
T1.start()

一旦有了,如果您正在运行python 3,则可以制作一个像这样的python脚本,并将其粘贴到为cgi配置的任何文件夹中:

<Directory /srv/www/yoursite/public_html>
    Options +ExecCGI
    AddHandler cgi-script .py
</Directory>

答案 1 :(得分:0)

谢谢,这是一个很好的答案!

我刚刚将其添加到脚本test1.py中(atm no test2.py中的任何功能只是原始代码):

[...] 导入测试2 cgitb.enable()

T1 = threading.Thread(test2) T1.start()

[...]

尽管我注意到test2确实是由线程启动的,但是网页仍然永远等待着…… 您是否有办法让网页显示某些内容而不是等待?

请注意,我也尝试过:

pid = os.fork()
#if pid==0 then we are in the child process
if(pid==0):
    T1 = threading.Thread(test2)
    T1.start()
    #i would hope that here the child process is detached from making wait the CGI!! but no
else:
    print('Content-type: text/html\n\n')
    print('<h1>Python Script Test</h1>')
    form = cgi.FieldStorage()
    tempThVal = form['tempThresh'].value
    print('Temperature threshold= ' + tempThVal)

但是仍然该死的浏览器正在等待它完成!!

答案 2 :(得分:0)

要解决此问题,您可以将自己的解决方案与我的答案结合起来以获得正确的答案。

#in test1.py

class my_thread(threading.Thread):
    def __init__(self):
        super().__init__()

    def run(self):
        p = subprocess.Popen([sys.executable, '/var/www/cgi-bin/test2.py'],
                 stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
        ########################
        #or your test2 statment#
        ########################
pid = os.fork()
#if pid==0 then we are in the child process
if(pid==0):
    T1 = my_thread()
    T1.start()
#i would hope that here the child process is detached from making wait the CGI!! but 
no
else:
   print('Content-type: text/html\n\n')
   print('<h1>Python Script Test</h1>')
   form = cgi.FieldStorage()
   tempThVal = form['tempThresh'].value
   print('Temperature threshold= ' + tempThVal)

我使用此方法在Django框架中解决了此问题

答案 3 :(得分:0)

让我发布最新的代码(以防您发现某些东西)

#include <stdlib.h>


// (3) Node (of a linked list), represents a single word indexed first letter of-
// column[i] and second letter of row[i]. Think of the z axis of a table

typedef struct _node
{
    char *value;
    struct _node *next;
}
node;


// (2) Row, represents the second letter of a word. Think of the y axis of a table

typedef struct _row
{
    node rows[26];
}
row;


// (1) Column, represents the first letter of a word. Think of the x axis of a table

typedef struct _column
{
    row columns[26];
}
column;


// These are detailed below

void init_table(column *table);
void free_memory(column *table);

column hash_table;


int main(void)
{

    init_table(&hash_table);
    free_memory(&hash_table);

    return 0;
}


// Initialize node-heads. If I don't do this, I get a 'runtime error: null-
// pointer passed as argument' when I want to access and store something in 
// "node->next" or "node->value" for the first time

void init_table(column *table)
{
    for (int i = 0; i < 26; i++)  // For each column
    {
        for (int j = 0; j < 26; j++)  // For each row
        {
            // Allocate space for a new node, as the head of a linked list.
            // Max word length will be 45 letters, allocate that much space
            node *first_node = malloc(sizeof(char) * 46 + sizeof(node *));

            // Assign new node with value of "none", and "next" (pointer) of NULL
            *first_node = (node) { .value = "none", .next = NULL };

            // Store this node in the current table cell
            table->columns[i].rows[j] = *first_node;
        }
    }
}


// Free all the memory on the heap, allocated previously
void free_memory(column *table)
{
    node *ptr;  // To guide the "del_node"
    node *del_node;  // To delete guided memory locations
    for (int i = 0; i < 26; i++)  // columns
    {
        for (int j = 0; j < 26; j++)  // rows
        {
            // Address of the first node of the current linked list
            ptr = &table->columns[i].rows[j];

            while(1)
            {
                if(ptr->next)  // If node does not point to "NULL"
                {
                    del_node = ptr;  // Guide the "del_node"
                    ptr = ptr->next;  // Advance "ptr" to the next node
                    free(del_node);  // Free the memory pointed by "del_node"
                }
                else {
                    break;
                }
            }

            // Free "ptr" in case there was no next node but "ptr" 
            // was pointing to a node

            if (ptr) free(ptr);
        }
    }
}