我的Google App脚本正在遍历用户的google驱动器文件,并且有时将文件复制并移动到其他文件夹。该脚本始终在5分钟后停止,并且日志中没有错误消息。

我一次运行要整理数十个甚至数千个文件。

是否有任何设置或解决方法?

评论

您可以通过使用HTML服务在您的工作子集上启动脚本的单独“迭代”来弯曲规则。布鲁斯·麦克弗森(Bruce McPherson)对此发表了博客。

如果您是企业客户,则现在可以注册App Maker的抢先体验,其中包括灵活的配额。

相关:stackoverflow.com/q/63604878

#1 楼

您可以做的一件事(这当然取决于您要完成的工作)是:

将必要的信息(例如,循环计数器)存储在电子表格或另一个永久存储区(例如ScriptProperties)中
让脚本每五分钟左右终止一次。
设置一个时间驱动的触发器,每五分钟运行一次脚本(或使用Script服务以编程方式创建触发器)。
运行从您使用过的永久性存储中读取保存的数据,然后继续从脚本停止的地方运行该脚本。

如果您发布了自己的解决方案,这不是一种千篇一律的解决方案代码人员可以更好地为您提供帮助。足以触发新触发器。 (我将其设置为5分钟,但我认为可能会少于该时间。)
注意#2:REASONABLE_TIME_TO_WAIT必须是一个执行速度相对较快的函数(我说少于1分钟)。
注意#3:Google已弃用doSomeWork(),并代之以引入Script Properties
注意#4:第二次调用该函数时,它将for循环的第i个值作为字符串。所以必须将其转换为整数

评论


触发器可以执行的频率是否有限制?我认为每24小时可能会有一个触发限制,等等。谢谢!

–卡林
15年2月27日在18:52

我认为这不适用于附加组件。附加定时触发仅允许每小时执行一次。您是否知道任何其他解决方案来保持任务运行并处理excel表格中的大量数据。

–天使
2015年4月29日19:30在

Google已弃用这种方法。还有其他选择吗? developers.google.com/apps-script/reference/properties/…

–iamtoc
16-2-5在15:06



@iamtoc禁用脚本属性时,您仍然可以使用PropertiesService。这是一个很小的编辑

– JZL003
16-2-26在15:21

REASONABLE_TIME_TO_WAIT的用途是什么,我们不能只做.at(new Date(currTime))吗?

–Valip
16年11月11日在19:12

#2 楼

配额


单个脚本的最大执行时间为每次执行6分钟
-https://developers.google.com/apps-script/guides/services/quotas


但是要熟悉其他限制。例如,您只允许每天1小时的总触发器运行时间,因此不能将一个长函数分成12个不同的5分钟块。

优化

也就是说,您真正需要花六分钟时间执行的理由很少。 JavaScript在几秒钟内排序数千行数据应该没有问题。对Google Apps本身的服务调用可能会损害您的性能。


您可以编写脚本以最大程度地利用内置缓存,从而最大限度地减少读写次数。交替进行读写命令很慢。要加速脚本,请使用一个命令将所有数据读入数组,对数组中的数据执行任何操作,然后使用一个命令将数据写出。
-https://developers.google.com/ apps-script / best_practices


批处理

您可能要做的最好的事情就是减少服务调用的次数。 Google通过允许大多数API调用的批处理版本来实现此目的。

作为一个简单的示例,代替此:

 for (var i = 1; i <= 100; i++) {
  SpreadsheetApp.getActiveSheet().deleteRow(i);
}
 


执行以下操作:

 SpreadsheetApp.getActiveSheet().deleteRows(i, 100);
 


在第一个循环中,您不仅需要通话100次删除工作表上的行,但您还需要同时获得活动工作表100次。第二个变体应比第一个变体执行好几个数量级。

交织的读写操作

此外,您还应该非常小心,不要在阅读和写作之间频繁往返。您不仅会损失批量操作的潜在收益,而且Google将无法使用其内置的缓存。


每次读取时,我们都必须先清空(提交)以确保您正在读取最新数据(可以通过调用SpreadsheetApp.flush()强制写入高速缓存)。同样,每次您执行写操作时,我们都必须丢弃读缓存,因为它不再有效。因此,如果可以避免交错的读写操作,则可以充分利用缓存。
-http://googleappsscript.blogspot.com/2010/06/optimizing-spreadsheet-operations.html


例如,代替以下内容:

 sheet.getRange("A1").setValue(1);
sheet.getRange("B1").setValue(2);
sheet.getRange("C1").setValue(3);
sheet.getRange("D1").setValue(4);
 


this:

 sheet.getRange("A1:D1").setValues([[1,2,3,4]]);
 


链式函数调用

最后如果您的函数真的不能在六分钟之内完成,您可以将调用链接在一起或拆分函数以处理较小的数据段。

您可以将数据存储在“缓存服务”(临时)或“属性服务”(永久)存储桶中,以跨执行检索(因为Google Apps脚本具有无状态执行)。

如果如果要开始其他事件,则可以使用Trigger Builder Class创建自己的触发器,或者在紧迫的时间表上设置重复发生的触发器。

评论


感谢KyleMit,这是一个非常全面的答案!

– Laurent'
15年6月16日在19:33

“也就是说,您真正需要花六分钟时间执行的理由很少。”尝试编写处理例如Gmail,云端硬盘等中的内容...

–user541686
19-2-27在1:25



@Mehrdad,这些似乎有几个原因:)但是,是的,不应将95%以上的脚本作为障碍

– KyleMit
19年2月27日在5:10

#3 楼

另外,请尽量减少对Google服务的呼叫量。例如,如果您要更改电子表格中的某个单元格范围,则不要读取每个单元格,都不要对其进行变异并存储回去。
而是将整个范围(使用Range.getValues())读入内存,对其进行更改并一次存储所有内容(使用Range.setValues())。

这将节省大量执行时间。

#4 楼

安东·索拉多(Anton Soradoi)的回答似乎还可以,但是请考虑使用缓存服务,而不是将数据存储到临时表中。

 function getRssFeed() {
   var cache = CacheService.getPublicCache();
   var cached = cache.get("rss-feed-contents");
   if (cached != null) {
     return cached;
   }
   var result = UrlFetchApp.fetch("http://example.com/my-slow-rss-feed.xml"); // takes 20 seconds
   var contents = result.getContentText();
   cache.put("rss-feed-contents", contents, 1500); // cache for 25 minutes
   return contents;
 }


还请注意,自2014年4月起,脚本运行时限制为6分钟。


G Suite业务/企业/教育和早期访问用户:

截至2018年8月,这些脚本的最大脚本运行时间现在设置为30分钟用户。

评论


在我看来,这是解决问题的最简单方法,因为您无需设置也不关心任何其他资源(电子表格,数据库等),并且所有脚本逻辑都保留在脚本本身内。谢谢!

– dubrox
16年1月15日在3:40

您能举一个通用函数的例子吗?

– Br。萨彦
16年2月24日在5:46

#5 楼

找出一种可以分散工作的方法,因此只需不到6分钟的时间,因为这是任何脚本的限制。在第一遍中,您可以迭代并在电子表格中存储文件和文件夹的列表,并为第2部分添加时间驱动的触发器。

在第2部分中,您可以在列表中删除每个条目处理它。如果列表中没有项目,请删除触发器。由于调用电子表格的次数众多,因此超时,但是在触发器再次运行时继续。

评论


确切地说,最大执行时间为6分钟:“当前最大脚本执行时间限制(6分钟)”,如此处developers.google.com/apps-script/scriptdb所述

– Peter H
13年1月22日在10:05

谢谢,我已经解决了。另外,我为脚本使用了10分钟的触发器,以确保执行之间没有重叠。我不确定Google如何决定启动时间驱动的触发器,因此不会有什么缓冲。

–弗雷德
13年1月22日在12:51

因此,您可以将所有数据存储到ScriptDb中,只做一小部分(由于6分钟的限制),然后继续进行下一次运行(将由计时器触发)。听起来不错的解决方案。

– Martin V.
13年1月22日在21:27

另外,您现在可以在任何时候创建触发器,因此,我的脚本会在每次启动后的7分钟内创建一个触发器(如果知道必须继续进行的话)。

–弗雷德
13年4月23日在1:22

#6 楼

我使用ScriptDB来保存自己的位置,同时循环处理大量信息。该脚本可以/确实超过了5分钟的限制。通过在每次运行期间更新ScriptDb,脚本可以从db中读取状态,并从中断状态开始直到所有处理完成为止。尝试一下此策略,我想您会对结果感到满意。

评论


使用在电子表格上的750个电子邮件地址中迭代的脚本也有类似的问题。如何存储脚本停止的位置并恢复执行?

– jwesonga
2012年10月4日,9:34

您能否提供更多详细信息...示例代码(如果可能)..或链接到更多详细信息。

–爱德华·O。
17年11月21日在18:03

ScriptDb已弃用。

–鲁本
18年1月2日在19:54

#7 楼

如果您使用的是G Suite商业版或企业版。
您可以在启用App maker的脚本运行时间后将运行时间从6分钟增加到30分钟:)

有关应用程序制造商的更多详细信息,请单击此处

评论


是的,我们可以使用抢先体验计划将运行时间从6分钟增加到30分钟,但是这些应用无法部署到公共场所。

–Sharath
18年4月22日在7:45

App Maker产品将于2021年1月19日关闭,support.google.com / a / answer / 9682494?p = am_announcement

–霍莉国王
6月11日15:36

除了App Maker即将关闭外,无需注册即可抢先获得30分钟的限制。

–鲁本
6月16日下午16:28

#8 楼

如果您是企业客户,则现在可以注册抢先体验App Maker,其中包括灵活配额。


在灵活配额系统下,此类硬配额限制已删除。脚本达到配额限制后不会停止。而是将它们延迟到配额可用之前,此时脚本将恢复执行。一旦开始使用配额,便会按固定比例重新填充配额。为了合理使用,脚本延迟很少发生。


#9 楼

如果您将G Suite用作企业,企业或EDU客户,则运行脚本的执行时间设置为:

30分钟/执行时间

请参阅:https:// developers.google.com/apps-script/guides/services/quotas