从Python 3运行本地JavaScript函数

时间:2018-09-11 05:36:12

标签: javascript python

因此,我正在自学各种AI技术,我想最好的方法是创建自己的Python机器人,该机器人可以使用在线开源Pokemon模拟器玩Pokemon游戏。

问题是该模拟器的所有源代码都是用JavaScript编写的,而我的机器人则使用Python。最初,我通过下载服务器的.js文件解决了获取有效Pokemon完整列表的问题,该文件(方便地)包含所有有效Pokemon /动作作为JSON对象,可以轻松导入到Python中。当我只需要Pokemon名称之类的时候,这一切都很好,但是现在,我在构建实际的引擎时,我发现它使用相同的JSON文件作为其实际的游戏代码。

例如,这是神奇宝贝“能力” Aftermath。请注意onAfterDamage

"aftermath": {
    desc: "If this Pokemon is knocked out with a contact move, that move's user loses 1/4 of its maximum HP, rounded down. If any active Pokemon has the Damp Ability, this effect is prevented.",
    shortDesc: "If this Pokemon is KOed with a contact move, that move's user loses 1/4 its max HP.",
    id: "aftermath",
    name: "Aftermath",
    onAfterDamageOrder: 1,
    onAfterDamage: function (damage, target, source, move) {
        if (source && source !== target && move && move.flags['contact'] && !target.hp) {
            this.damage(source.maxhp / 4, source, target);
        }
    },
    rating: 2.5,
    num: 106,
}

如您所见,onAfterDamage是一种JavaScript函数,据我所知,我无法轻易地从Python调用它。所以现在我正处于十字路口:

  1. 停止从服务器获取.js文件,并完全用Python编写我自己的代码,本质上是自己“翻译” JavaScript代码。

  2. 用JavaScript而不是Python重写我的整个机器人,尽管我对JavaScript的经验和适应程度要差得多。

  3. 找到一种方法,运行从我的Python机器人内部从服务器下载的JavaScript代码,从该代码内部调用任意函数并返回结果。

选项1的问题很快就过时了-当引入新的Pokemon机制或创建新的Pokemon时,我不会“免费”获得它-我必须找出发生了什么变化并自己实施更改。

我想避免选择2只是因为我不太习惯编写JavaScript-过去我曾涉猎这一点,但它与我最喜欢的语言相去甚远,不是我想在什么时候处理的这不是我项目的主要重点。

我意识到选项3带来了相当大的安全风险-同时我有把握地确定,不会有中间人会对该机器人进行中间人攻击,除非我自己,否则可能没人会使用,我仍然只是从某处的服务器上下载随机JavaScript并尝试执行它。

我见过类似PyExecJS之类的东西,但是它们不再得到维护,而且我还没有真正看到有人推荐过类似的替代品。 PyExecJS的功能正是我正在寻找的功能(即功能execjs.eval(js_code)),但是我不确定我是否要使用已经达到停产状态的产品。 I've seen the answers here,但他们不建议您替换PyExecJS;他们只会向该用户表明他们使用的是错误的。

我还看到人们建议使用Selenium或运行无头浏览器,但是我不确定是否要处理所有这些额外的开销。我在校外做过的第一个编程项目与此非常相似,我最终使用Selenium用Java对其进行编码。我对该体验感到不满意,并且我不希望再次这样做,尤其是当我只需要执行已经在本地下载的JavaScript时。

我在这里完全脱离基地了吗?我应该采取另一种方法,还是我应该手工将所有这些JS代码转换为Python?

1 个答案:

答案 0 :(得分:0)

理想情况下,您可以像其他任何可执行文件一样从cli运行.js文件。使用node -e,您可以在cli上执行JavaScript代码。

关于此帖子https://stackoverflow.com/a/450329/6478277,您可以类似地在本地节点上运行脚本。

node -e "function func(){console.log(123)};func();"

来自文件

print subprocess.check_output(['node -e "require(\"./file.js\").test()"'])

file.js可能类似于

   module.exports = {
     test: () => console.log(123),
   }