繁体   English   中英

通过Java执行python脚本

[英]Execute python script through Java

我正在尝试运行一个非常简单的 python 脚本,该脚本从 java 内部清除并写入 CSV 文件,但我遇到了很多麻烦。

The scripts don't require any input and the output is all written into a CSV file so all I need to do is get the python scripts to run through my java code.

下面是我在互联网上看到的一些代码,但似乎对我不起作用。 似乎对于这两个脚本,使用此命令对 csv 没有任何作用。 不会抛出任何错误,并且 java 程序可能只是在不执行 python 脚本的情况下退出。

public static void main(String[] args) throws IOException
    {
        Process p = Runtime.getRuntime().exec("python Refresh.py");
    }

这是我要运行的脚本。

脚本1:

file = open("products.csv","r+")
file.truncate(0)
file.close()

脚本2:

from bs4 import BeautifulSoup as soup
from urllib.request import Request, urlopen
import time

filename = "products.csv"
f = open(filename, "a")


#connects to the page and reads and saves raw HTML
for i in (0,25,50,75):
    my_url = 'https://www.adorama.com/l/Computers/Computer-Components/Video-and-Graphics-Cards?startAt='+ str(i) +'&sel=Expansion-Ports_HDMI'
    hdr = {'User-Agent': 'Mozilla/5.0'}
    client = Request(my_url,headers=hdr)
    page = urlopen(client).read()

    #parsing the HTML
    page_soup = soup(page, "html.parser")
    #print (page_soup.h1)

    containers = page_soup.findAll("div",{"class":"item"})
    #print (len(containers))
    containers.pop()
    for container in containers:
        
        title_container = container.findAll("div",{"class":"item-details"})
        title = title_container[0].h2.a.text.strip()

        status_container = container.findAll("div",{"class":"item-actions"})
        status = status_container[0].form.button.text.strip()

        if (status == "Temporarily not available"):
            status = "Out of stock"
        else:
            status = "In stock"
        
        price = container.find("div","prices").input["value"]

        link = container.a["href"]

        f.write(title.replace(",", "|") + "," + price.replace(",", "") + "," + status + "," + link + "\n")

        time.sleep(0.01)
f.close()

java 文件、Python 脚本和 csv 文件都在同一个文件夹中。

使用较新的 ProcessBuilder class:

ProcessBuilder pb = new ProcessBuilder("python","Refresh.py");
Process p = pb.start();

希望对你有用!

您没有检查 python 脚本中的错误。 您可以通过将 STDERR 合并到 STDOUT 并将 STDOUT 的内容报告给控制台来简单地实现这一点:

Process p = new ProcessBuilder("python", "Refresh.py")
            .redirectErrorStream(true)
            .start();
p.getInputStream().transferTo(System.out);
int rc = p.waitFor();

这应该会打印出 python 的错误消息并返回错误代码。 您可能有文件路径问题,因此您可能需要将 arguments 调整为“python”和/或“Refresh.py”的显式路径名。

我设法通过不断阅读 Python 文件的“打印”和错误输出来解决这个问题。 虽然我仍然不完全理解这是如何解决问题的,但我最好的猜测是,有了这个,Java 代码保持 python 脚本“运行”,直到脚本本身完成它的工作,而不是仅仅打开脚本并立即继续。

这是代码:

import java.io.BufferedReader;
import java.io.InputStreamReader;

public class Test {

    public static void main(String... args) throws Exception {

        String[] callAndArgs = {"python3", "YourScript.py"};
        Process p = Runtime.getRuntime().exec(callAndArgs);
        
        BufferedReader stdInput = new BufferedReader(new InputStreamReader(p.getInputStream()));
        BufferedReader stdError = new BufferedReader(new InputStreamReader(p.getErrorStream()));
        
        String s;
        while ((s = stdInput.readLine()) != null) {
            //System.out.println(s);
        }

        while ((s = stdError.readLine()) != null) {
            //System.out.println(s);
        }

    }

}

另一个值得注意的细节是,此代码似乎仅在编译并通过终端/Geany 运行时才有效。 如果我用 IntelliJ 运行相同的东西,它就不起作用 再一次,我不确定为什么会这样,但我怀疑 IntelliJ 可以在某种虚拟机中编译和运行。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM