Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/python-3.x/18.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python 3.x 谷歌云功能与魔杖停止工作_Python 3.x_Google Cloud Platform_Google Cloud Functions - Fatal编程技术网

Python 3.x 谷歌云功能与魔杖停止工作

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

我已经设置了3个Google Cloud Storge bucket和3个函数(每个bucket对应一个函数),当PDF文件上传到bucket时会触发这些函数。函数将PDF转换为png图像并进行进一步处理

当我试图创建第四个bucket和类似的函数时,奇怪的是它不起作用。即使我复制了现有的3个函数中的一个,它仍然不起作用,并且我得到了以下错误:

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)