Python 3.x 谷歌云功能与魔杖停止工作
我已经设置了3个Google Cloud Storge bucket和3个函数(每个bucket对应一个函数),当PDF文件上传到bucket时会触发这些函数。函数将PDF转换为png图像并进行进一步处理 当我试图创建第四个bucket和类似的函数时,奇怪的是它不起作用。即使我复制了现有的3个函数中的一个,它仍然不起作用,并且我得到了以下错误:Python 3.x 谷歌云功能与魔杖停止工作,python-3.x,google-cloud-platform,google-cloud-functions,Python 3.x,Google Cloud Platform,Google Cloud Functions,我已经设置了3个Google Cloud Storge bucket和3个函数(每个bucket对应一个函数),当PDF文件上传到bucket时会触发这些函数。函数将PDF转换为png图像并进行进一步处理 当我试图创建第四个bucket和类似的函数时,奇怪的是它不起作用。即使我复制了现有的3个函数中的一个,它仍然不起作用,并且我得到了以下错误: Traceback(最近一次调用):文件“/env/local/lib/python3.7/site packages/google/cloud/fun
Traceback(最近一次调用):文件“/env/local/lib/python3.7/site packages/google/cloud/functions\u v1beta2/worker.py”,第333行,在run\u background\u function\u function\u handler.invoke\u user\u function(event\u object)文件“/env/local/lib/python3.7/site packages/google/cloud/functions\u v1beta2/worker.py”,第199行,调用用户函数返回调用用户函数(请求或事件)文件“/env/local/lib/python3.7/site packages/google/cloud/functions\u v1beta2/worker.py”,第196行,调用用户函数事件上下文(**请求或事件上下文))文件“/user\u code/main.py”,第27行,pdf格式,带图像(文件名=tmp\u pdf,分辨率=300)如图所示:文件“/env/local/lib/python3.7/site packages/wand/image.py”,第2874行,在文件“/env/local/lib/python3.7/site packages/wand/image.py”中,第2952行,在文件“/env/local/lib/python3.7/site packages/wand/resource.py”中,第222行,在文件“/env/local/lib/python3.7/resource packages/wand/resource.py”中,在raise_异常中raise e wand.exceptions.PolicyError:未授权
/tmp/tmphm3hiezy'@error/compose.c/ReadImage/412`
为什么相同的函数在现有的bucket上工作,而在新的bucket上却不工作,这让我感到困惑
更新:
即使这样也不起作用(获取“缓存资源耗尽”错误):
在requirements.txt
中:
google-cloud-storage
wand
在main.py
中:
import tempfile
from google.cloud import storage
from wand.image import Image
storage_client = storage.Client()
def pdf_to_img(data, context):
file_data = data
pdf = file_data['name']
if pdf.startswith('v-'):
return
bucket_name = file_data['bucket']
blob = storage_client.bucket(bucket_name).get_blob(pdf)
_, tmp_pdf = tempfile.mkstemp()
_, tmp_png = tempfile.mkstemp()
tmp_png = tmp_png+".png"
blob.download_to_filename(tmp_pdf)
with Image(filename=tmp_pdf) as image:
image.save(filename=tmp_png)
print("Image created")
new_file_name = "v-"+pdf.split('.')[0]+".png"
blob.bucket.blob(new_file_name).upload_from_filename(tmp_png)
上面的代码应该只是创建一个上传到bucket的图像文件的副本 这是,我们正在为应用程序引擎和云功能开发一个解决方案。这实际上似乎是使用PDF格式的ImageMagick相关功能的一个障碍。我们通过定制docker在Google App engine上部署的类似代码失败,在缺少授权时出现相同错误 我不知道如何在GAE或GCF上编辑policy.xml文件,但其中的一行必须更改为:
<policy domain="coder" rights="read|write" pattern="PDF" />
在我们等待Ubuntu解决这个问题时,我按照@DustinIngram的建议,在ComputeEngine中创建了一个安装了ImageMagick的虚拟机。缺点是我现在有了第二个API,我的应用程序引擎中的API必须调用它,只是为了生成图像。话虽如此,它对我来说很有效。这是我的设置: 主要API: 当pdf文件上载到云存储时,我称之为:
response = requests.post('http://xx.xxx.xxx.xxx:5000/makeimages', data=data)
其中数据是格式为{“file\u name”:file\u name}
在VM上运行的API上,POST
请求得到如下处理:
@app.route('/makeimages', methods=['POST'])
def pdf_to_jpg():
file_name = request.form['file_name']
blob = storage_client.bucket(bucket_name).get_blob(file_name)
_, temp_local_filename = tempfile.mkstemp()
temp_local_filename_jpeg = temp_local_filename + '.jpg'
# Download file from bucket.
blob.download_to_filename(temp_local_filename)
print('Image ' + file_name + ' was downloaded to ' + temp_local_filename)
with Image(filename=temp_local_filename, resolution=300) as img:
pg_num = 0
image_files = {}
image_files['pages'] = []
for img_page in img.sequence:
img_page_2 = Image(image=img_page)
img_page_2.format = 'jpeg'
img_page_2.compression_quality = 70
img_page_2.save(filename=temp_local_filename_jpeg)
new_file_name = file_name.replace('.pdf', 'p') + str(pg_num) + '.jpg'
new_blob = blob.bucket.blob(new_file_name)
new_blob.upload_from_filename(temp_local_filename_jpeg)
print('Page ' + str(pg_num) + ' was saved as ' + new_file_name)
image_files['pages'].append({'page': pg_num, 'file_name': new_file_name})
pg_num += 1
try:
os.remove(temp_local_filename)
except (ValueError, PermissionError):
print('Could not delete the temp file!')
return jsonify(image_files)
这将从云存储下载pdf,为每个页面创建一个图像,并将其保存回云存储。然后,API将返回一个JSON文件以及创建的图像文件列表
因此,这不是最优雅的解决方案,但至少我不需要手动转换文件。因为该漏洞已在Ghostscript中修复,但未在ImageMagick中更新,所以在Google Cloud函数中将PDF转换为图像的解决方法是使用该方法,并直接从Ghostscript请求PDF转换为png(绕过ImageMagick) requirements.txt
google-cloud-storage
ghostscript==0.6
main.py
import locale
import tempfile
import ghostscript
from google.cloud import storage
storage_client = storage.Client()
def pdf_to_img(data, context):
file_data = data
pdf = file_data['name']
if pdf.startswith('v-'):
return
bucket_name = file_data['bucket']
blob = storage_client.bucket(bucket_name).get_blob(pdf)
_, tmp_pdf = tempfile.mkstemp()
_, tmp_png = tempfile.mkstemp()
tmp_png = tmp_png+".png"
blob.download_to_filename(tmp_pdf)
# create a temp folder based on temp_local_filename
# use ghostscript to export the pdf into pages as pngs in the temp dir
args = [
"pdf2png", # actual value doesn't matter
"-dSAFER",
"-sDEVICE=pngalpha",
"-o", tmp_png,
"-r300", tmp_pdf
]
# the above arguments have to be bytes, encode them
encoding = locale.getpreferredencoding()
args = [a.encode(encoding) for a in args]
#run the request through ghostscript
ghostscript.Ghostscript(*args)
print("Image created")
new_file_name = "v-"+pdf.split('.')[0]+".png"
blob.bucket.blob(new_file_name).upload_from_filename(tmp_png)
无论如何,这可以让您绕过这个问题,并将所有处理都保留在GCF中。希望它能有所帮助。您的代码适用于单页pdf。我的使用案例是用于多页pdf转换、重影脚本代码和解决方案。没有魔杖(imagemgick)功能正常。我尝试裁剪图像,但出现了以下错误:wand.exceptions.CacheError:cache resources expensed`/tmp/tmpt7_1dq6i'@error/cache.c/OpenPixelCache/3984I我不知道这是否相关,但如果服务器已针对imagemagick进行更新,则可能会添加对PDF文件的安全策略限制,因为现在已修复的Ghostscript。如果您放松策略限制,它可能会再次工作。请参阅@fmw42您所说的是真的,但如果您观察我上面发布的代码,Wand module甚至没有创建PNG文件的副本。此外,我还尝试从云函数中编辑
policy.xml
,但没有工作。@Naveed您成功了吗我正在尝试编写一个非常类似的函数(将pdf的每一页转换为jpeg),我得到的是相同的wand.exceptions.PolicyError:未授权@RogB不,它仍然不工作。我正在使用pdf2image在我的计算机上进行pdf到PNG(你也可以进行jpeg)的转换(将并发设置为3以加快处理速度),然后将图像发送到云存储桶进行进一步处理。如果我在新的谷歌云帐户上创建一个新存储桶,并使用我的3个函数之一(在各自的旧存储桶上运行良好),我会收到相同的错误。此外,我还尝试分配2GB内存(最高)到我的GC函数。这一切都是徒劳的。谢谢,我可以复制它。查看它。如果我们在本地计算机中遇到这样的错误,我们必须在/etc/ImageMagick中编辑policy.xml文件,但在云函数中不能这样做。看起来当前GC函数部署中存在一些问题,而几周前部署的函数工作正常。Dustin:正在等待您的响应。Wand无法将pdf转换为png,获取“策略错误,未授权”。我相信这与ImageMagick的policy.xml文件有关。我已在内部提交了一个问题,解决后将在此处更新。感谢您的输入。很遗憾,我无法使用app engine,因为它不适合长时间运行的后台进程。我正在处理数千个PDF。我尝试了AWS lambda函数
import locale
import tempfile
import ghostscript
from google.cloud import storage
storage_client = storage.Client()
def pdf_to_img(data, context):
file_data = data
pdf = file_data['name']
if pdf.startswith('v-'):
return
bucket_name = file_data['bucket']
blob = storage_client.bucket(bucket_name).get_blob(pdf)
_, tmp_pdf = tempfile.mkstemp()
_, tmp_png = tempfile.mkstemp()
tmp_png = tmp_png+".png"
blob.download_to_filename(tmp_pdf)
# create a temp folder based on temp_local_filename
# use ghostscript to export the pdf into pages as pngs in the temp dir
args = [
"pdf2png", # actual value doesn't matter
"-dSAFER",
"-sDEVICE=pngalpha",
"-o", tmp_png,
"-r300", tmp_pdf
]
# the above arguments have to be bytes, encode them
encoding = locale.getpreferredencoding()
args = [a.encode(encoding) for a in args]
#run the request through ghostscript
ghostscript.Ghostscript(*args)
print("Image created")
new_file_name = "v-"+pdf.split('.')[0]+".png"
blob.bucket.blob(new_file_name).upload_from_filename(tmp_png)