草庐IT

python - 子进程在 docker 容器中不起作用

coder 2023-05-28 原文

我真的快疯了,把头发拔了,因为我似乎无法解决这个特殊问题。

所以问题来了:我有两个容器:Django 和 celery。用户上传一个 word 文档,celery worker 将该 word 文档转换为 pdf 并上传到 s3 存储桶。我正在使用 libreoffice --headless 来转换它。因此,用户将文件发送到 API 端点并将 word 文档保存在名为 original 的文件夹中,celery 调用 convert_office_to_pdf.delay 需要转换文件并将其放入另一个文件夹converted。除了 celery 功能外,一切都按预期工作。代码是这样的:

import subprocess    
def convert_office_to_pdf(original_file):
    ws = websocket.WebSocket()
        ws.connect('ws://web:8000/ws/converter/public/')
    #how the command will look like
        print('libreoffice --headless --convert-to pdf original/{} --outdir ./converted'.format(original_file))
        subprocess.call('libreoffice --headless --convert-to pdf original/{} --outdir ./converted'.format(original_file), shell=True)
     ws.send(json.dumps({
            'message': '{}.pdf'.format(pure_file_name), 
            'progress': 75}))
        upload_file_to_s3(pure_file_name, 'pdf', ws)

然而,函数 get 被执行了,什么也没有发生。这是 docker-compose

的输出
web_1       | [2018/03/22 22:57:52] HTTP GET /converter/ 200 [0.06, 172.17.0.1:32788]
web_1       | [2018/03/22 22:57:52] HTTP GET /static/css/normalize.css 304 [0.02, 172.17.0.1:32788]
web_1       | [2018/03/22 22:57:52] WebSocket HANDSHAKING /ws/converter/public/ [172.17.0.1:32798]
web_1       | [2018/03/22 22:57:52] WebSocket CONNECT /ws/converter/public/ [172.17.0.1:32798]
fileshiffty_data_1 exited with code 0
worker_1    | [2018-03-22 22:58:04,413: INFO/MainProcess] Received task: api.tasks.convert_office_to_pdf[287805aa-3c9c-4212-92d4-cac5872076f2]  
worker_1    | [2018-03-22 22:58:04,414: DEBUG/MainProcess] TaskPool: Apply <function _fast_trace_task at 0x7fb72d567e18> (args:('api.tasks.convert_office_to_pdf', '287805aa-3c9c-4212-92d4-cac5872076f2', {'lang': 'py', 'task': 'api.tasks.convert_office_to_pdf', 'id': '287805aa-3c9c-4212-92d4-cac5872076f2', 'eta': None, 'expires': None, 'group': None, 'retries': 0, 'timelimit': [None, None], 'root_id': '287805aa-3c9c-4212-92d4-cac5872076f2', 'parent_id': None, 'argsrepr': "('1521759484.3458297-Doc1.docx',)", 'kwargsrepr': '{}', 'origin': 'gen8@a478d8966021', 'reply_to': 'adf32365-ef93-327e-842f-7eff10fda37a', 'correlation_id': '287805aa-3c9c-4212-92d4-cac5872076f2', 'delivery_info': {'exchange': '', 'routing_key': 'celery', 'priority': 0, 'redelivered': None}}, b'[["1521759484.3458297-Doc1.docx"], {}, {"callbacks": null, "errbacks": null, "chain": null, "chord": null}]', 'application/json', 'utf-8') kwargs:{})
web_1       | [2018/03/22 22:58:04] HTTP PUT /api/v1/fileupload/word/pdf/ 200 [0.07, 172.17.0.1:32788]
worker_1    | [2018-03-22 22:58:04,417: DEBUG/MainProcess] Task accepted: api.tasks.convert_office_to_pdf[287805aa-3c9c-4212-92d4-cac5872076f2] pid:9
web_1       | [2018/03/22 22:58:04] WebSocket HANDSHAKING /ws/converter/public/ [172.17.0.2:58928]
web_1       | [2018/03/22 22:58:04] WebSocket CONNECT /ws/converter/public/ [172.17.0.2:58928]
worker_1    | [2018-03-22 22:58:04,426: WARNING/ForkPoolWorker-2] /data/web/fileshiffty
worker_1    | [2018-03-22 22:58:04,427: WARNING/ForkPoolWorker-2] libreoffice --headless --convert-to pdf original/1521759484.3458297-Doc1.docx --outdir ./converted
web_1       | {"message": "1521759484.3458297-Doc1.pdf", "progress": 50}
web_1       | {"message": "1521759484.3458297-Doc1.pdf", "progress": 75}

当我上传文件时,我可以确认文件已添加到 original 文件夹和日志条目 worker_1 | [2018-03-22 22:58:04,427: WARNING/ForkPoolWorker-2] libreoffice --headless --convert-to pdf original/1521759484.3458297-Doc1.docx --outdir ./converted 显示什么命令subprocess 将调用。但是,当我查看 converted 文件夹时,我什么也没看到。它完全是空的。然而,奇怪的部分是当我 bash 进入 docker 容器并运行相同的东西时,文件得到转换并放入文件夹中。像这样

root@4b9da6f71226:/data/web/fileshiffty/api# python3
Python 3.6.4 (default, Mar 14 2018, 17:49:05) 
[GCC 4.9.2] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> import subprocess
>>> subprocess.call('libreoffice --headless --convert-to pdf original/1521759484.3458297-Doc1.docx --outdir ./converted', shell=True)
convert /data/web/fileshiffty/api/original/1521759484.3458297-Doc1.docx -> /data/web/fileshiffty/api/converted/1521759484.3458297-Doc1.pdf using writer_pdf_Export
0

为什么当我 bash 并执行子进程时它可以工作但不是从文件中。有人可以帮帮我吗?

编辑。似乎 subprocess 命令似乎没有被执行。我将代码更改为以下内容,以了解在 subprocess 命令之后会发生什么,甚至使用了像这样的绝对路径:

def convert_office_to_pdf(original_file):
    ws = websocket.WebSocket()
    ws.connect('ws://web:8000/ws/converter/public/')
    pure_file_name = os.path.splitext(os.path.basename(original_file))[0]
    ws.send(json.dumps({
        'message': '{}.pdf'.format(pure_file_name), 
        'progress': 50}))
    print(os.getcwd())
    print('libreoffice --headless --convert-to pdf original/{} --outdir ./converted'.format(original_file))
    command = ['libreoffice', '--headless', '--convert-to', 'pdf', '{}/original/{}'.format(os.getcwd(), original_file), '--outdir', '{}/converted'.format(os.getcwd())]
    process = subprocess.Popen(command, stdout=subprocess.PIPE)
    out, err = process.communicate()
    print(out)
    print(err)
    print('------------------------------------------------')
    ws.send(json.dumps({
        'message': '{}.pdf'.format(pure_file_name), 
        'progress': 75}))
    upload_file_to_s3(pure_file_name, 'pdf', ws)

我得到以下输出

 [2018-03-22 23:44:54,668: DEBUG/MainProcess] Task accepted: api.tasks.convert_office_to_pdf[721ed2db-6a74-4fd2-9484-0fca14df7c01] pid:9
web_1       | [2018/03/22 23:44:54] WebSocket HANDSHAKING /ws/converter/public/ [172.17.0.2:60898]
web_1       | [2018/03/22 23:44:54] WebSocket CONNECT /ws/converter/public/ [172.17.0.2:60898]
worker_1    | [2018-03-22 23:44:54,696: WARNING/ForkPoolWorker-2] /data/web/fileshiffty
worker_1    | [2018-03-22 23:44:54,696: WARNING/ForkPoolWorker-2] libreoffice --headless --convert-to pdf original/1521762293.8511283-Doc1.docx --outdir ./converted
web_1       | {"message": "1521762293.8511283-Doc1.pdf", "progress": 50}
worker_1    | [2018-03-22 23:44:55,283: WARNING/ForkPoolWorker-2] b''
worker_1    | [2018-03-22 23:44:55,283: WARNING/ForkPoolWorker-2] None
worker_1    | [2018-03-22 23:44:55,283: WARNING/ForkPoolWorker-2] ------------------------------------------------
web_1       | {"message": "1521762293.8511283-Doc1.pdf", "progress": 75}

print(out) 只打印一个空白字节,而 print(err) 只打印 None。

编辑 2 - 这是 docker-compose 文件

web:
  restart: always
  tty: true
  build: ./web/
  working_dir: /data/web/fileshiffty
  expose:
    - "8000"
  ports:
    - "8000:8000"
  links:
    - postgres:postgres
    - redis:redis
  env_file: env
  volumes:
    - ./web:/data/web
  command: bash -c "python3 manage.py runserver 0.0.0.0:8000"
  # command: /usr/bin/gunicorn fileshiffty.wsgi:application -w 2 -b :8000
nginx:
  restart: always
  build: ./nginx/
  ports:
    - "80:80"
  volumes_from:
    - web
  links:
    - web:web
postgres:
  restart: always
 image: postgres:latest
  volumes_from:
    - data
  volumes:
    - ./postgres/docker-entrypoint-initdb.d:/docker-entrypoint-initdb.d
    - ./backups/postgresql:/backup
  env_file:
    - env
  expose:
    - "5432"
redis:
  restart: always
  image: redis:latest
  expose:
    - "6379"
worker:
    build: ./web/
    working_dir: /data/web/fileshiffty
    command: bash -c "celery -A fileshiffty worker --loglevel=DEBUG"
    volumes:
      - ./web:/data/web
    links:
      - postgres:postgres
      - redis:redis
      - web:web
data:
  restart: always
  image: alpine
  volumes:
    - /var/lib/postgresql
  command: "true"

最佳答案

检查您开发代码时使用的 Python 版本,以及您构建容器时使用的版本是否相同。 我遇到了一个完全相同的问题。我正在使用 subprocess.call() 在我的代码中的命令行上执行某些操作。我的代码在我的本地机器上运行得非常好,但在尝试在 docker 容器内运行时在 subprocess.call() 处失败。奇怪的是,如果我在交互式 Python shell 中明确编写 subprocess.call() ,它会在 docker 内部运行。我什至尝试过使用 os.system()。同样的问题。

当我将 python 版本设置为相同时,最终解决了(最初它们是 3.7.3 用于开发版本,3.5 用于 docker 容器)。 我希望同样适用于你!

此外,如果其他人可以为我建议的这个肮脏修复添加更多技术见解,那就太好了。

关于python - 子进程在 docker 容器中不起作用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49439955/

有关python - 子进程在 docker 容器中不起作用的更多相关文章

  1. python - 如何使用 Ruby 或 Python 创建一系列高音调和低音调的蜂鸣声? - 2

    关闭。这个问题是opinion-based.它目前不接受答案。想要改进这个问题?更新问题,以便editingthispost可以用事实和引用来回答它.关闭4年前。Improvethisquestion我想在固定时间创建一系列低音和高音调的哔哔声。例如:在150毫秒时发出高音调的蜂鸣声在151毫秒时发出低音调的蜂鸣声200毫秒时发出低音调的蜂鸣声250毫秒的高音调蜂鸣声有没有办法在Ruby或Python中做到这一点?我真的不在乎输出编码是什么(.wav、.mp3、.ogg等等),但我确实想创建一个输出文件。

  2. ruby - 在 jRuby 中使用 'fork' 生成进程的替代方案? - 2

    在MRIRuby中我可以这样做:deftransferinternal_server=self.init_serverpid=forkdointernal_server.runend#Maketheserverprocessrunindependently.Process.detach(pid)internal_client=self.init_client#Dootherstuffwithconnectingtointernal_server...internal_client.post('somedata')ensure#KillserverProcess.kill('KILL',

  3. ruby - 通过 ruby​​ 进程共享变量 - 2

    我正在编写一个gem,我必须在其中fork两个启动两个webrick服务器的进程。我想通过基类的类方法启动这个服务器,因为应该只有这两个服务器在运行,而不是多个。在运行时,我想调用这两个服务器上的一些方法来更改变量。我的问题是,我无法通过基类的类方法访问fork的实例变量。此外,我不能在我的基类中使用线程,因为在幕后我正在使用另一个不是线程安全的库。所以我必须将每个服务器派生到它自己的进程。我用类变量试过了,比如@@server。但是当我试图通过基类访问这个变量时,它是nil。我读到在Ruby中不可能在分支之间共享类变量,对吗?那么,还有其他解决办法吗?我考虑过使用单例,但我不确定这是

  4. ruby-on-rails - 如果 Object::try 被发送到一个 nil 对象,为什么它会起作用? - 2

    如果您尝试在Ruby中的nil对象上调用方法,则会出现NoMethodError异常并显示消息:"undefinedmethod‘...’fornil:NilClass"然而,有一个tryRails中的方法,如果它被发送到一个nil对象,它只返回nil:require'rubygems'require'active_support/all'nil.try(:nonexisting_method)#noNoMethodErrorexceptionanymore那么try如何在内部工作以防止该异常? 最佳答案 像Ruby中的所有其他对象

  5. ruby-on-rails - s3_direct_upload 在生产服务器中不工作 - 2

    在Rails4.0.2中,我使用s3_direct_upload和aws-sdkgems直接为s3存储桶上传文件。在开发环境中它工作正常,但在生产环境中它会抛出如下错误,ActionView::Template::Error(noimplicitconversionofnilintoString)在View中,create_cv_url,:id=>"s3_uploader",:key=>"cv_uploads/{unique_id}/${filename}",:key_starts_with=>"cv_uploads/",:callback_param=>"cv[direct_uplo

  6. Python 相当于 Perl/Ruby ||= - 2

    这个问题在这里已经有了答案:关闭10年前。PossibleDuplicate:Pythonconditionalassignmentoperator对于这样一个简单的问题表示歉意,但是谷歌搜索||=并不是很有帮助;)Python中是否有与Ruby和Perl中的||=语句等效的语句?例如:foo="hey"foo||="what"#assignfooifit'sundefined#fooisstill"hey"bar||="yeah"#baris"yeah"另外,类似这样的东西的通用术语是什么?条件分配是我的第一个猜测,但Wikipediapage跟我想的不太一样。

  7. java - 什么相当于 ruby​​ 的 rack 或 python 的 Java wsgi? - 2

    什么是ruby​​的rack或python的Java的wsgi?还有一个路由库。 最佳答案 来自Python标准PEP333:Bycontrast,althoughJavahasjustasmanywebapplicationframeworksavailable,Java's"servlet"APImakesitpossibleforapplicationswrittenwithanyJavawebapplicationframeworktoruninanywebserverthatsupportstheservletAPI.ht

  8. 华为OD机试用Python实现 -【明明的随机数】 2023Q1A - 2

    华为OD机试题本篇题目:明明的随机数题目输入描述输出描述:示例1输入输出说明代码编写思路最近更新的博客华为od2023|什么是华为od,od薪资待遇,od机试题清单华为OD机试真题大全,用Python解华为机试题|机试宝典【华为OD机试】全流程解析+经验分享,题型分享,防作弊指南华为o

  9. python - 如何读取 MIDI 文件、更改其乐器并将其写回? - 2

    我想解析一个已经存在的.mid文件,改变它的乐器,例如从“acousticgrandpiano”到“violin”,然后将它保存回去或作为另一个.mid文件。根据我在文档中看到的内容,该乐器通过program_change或patch_change指令进行了更改,但我找不到任何在已经存在的MIDI文件中执行此操作的库.他们似乎都只支持从头开始创建的MIDI文件。 最佳答案 MIDIpackage会为您完成此操作,但具体方法取决于midi文件的原始内容。一个MIDI文件由一个或多个音轨组成,每个音轨是十六个channel中任何一个上的

  10. Get https://registry-1.docker.io/v2/: net/http: request canceled while waiting - 2

    1.错误信息:Errorresponsefromdaemon:Gethttps://registry-1.docker.io/v2/:net/http:requestcanceledwhilewaitingforconnection(Client.Timeoutexceededwhileawaitingheaders)或者:Errorresponsefromdaemon:Gethttps://registry-1.docker.io/v2/:net/http:TLShandshaketimeout2.报错原因:docker使用的镜像网址默认为国外,下载容易超时,需要修改成国内镜像地址(首先阿里

随机推荐