2016-03-22 18 views
4

私は、x秒ごとにtxtファイルに書き込むウィンドウズ(Win7)上のprogrammを持っています。 今、x秒ごとにこのtxtファイルを読むpythonスクリプトがあります。 pythonスクリプトがファイルを読み込むと同時に、もう一方のプログラムがそのファイルに書き込もうとしています。書き込みプログラムがクラッシュし、権限エラーが表示されます。私はプログラムがtxtファイルに書き込む方法を変更できないので、書き込みプログラムをブロックせずにtxtファイルを開こうとする必要があります。 誰かがこの状況で何ができるかを知っていますか(ブロッキングなしで読む) このトピックに関するすべてのヒントについて私は非常に満足しています!私は、そのユニコードに「コーデック」でファイルを開く必要がPythonはウィンドウ上でブロックされないファイルを読み込みます

with codecs.open(datapath, "r", 'utf-16') as raw_data: 

     raw_data_x = raw_data.readlines() 

ファイルを読み込もうとするプログラムのコードは次のようになります。

+0

この回答を確認http://stackoverflow.com/a/30172682/735893 – Vader

+0

すばやくお返事ありがとうございます!私はすでにその投稿を見た。私はそれが勝利システムのためではないと思う。 – Py42

+0

@Vader:そのリンクはUNIX固有の 'fcntl'を使用します.OPはWindowsを使用しています。 – cdarke

答えて

2

長い間、私はctypesであなたのためにそれを行う関数を作成することができました。このプロセスが「排他的」アクセス権を取得していない場合にのみ有効です。もしそうなら、運が悪いので、hereのようなシャドウコピーサービスを使うか、hereを実装する必要があります。
はとにかく、ここに行く:読み取りを共有し、複数のアクセスを可能に扱う書きながら

import ctypes 
from ctypes import wintypes 
import os 
import msvcrt 

GENERIC_READ = 0x80000000 
GENERIC_WRITE = 0x40000000 

OPEN_EXISTING = 3 
OPEN_ALWAYS = 4 

ACCESS_MODES = { 
    "r": GENERIC_READ, 
    "w": GENERIC_WRITE, 
    "r+": (GENERIC_READ|GENERIC_WRITE) 
} 

OPEN_MODES = { 
    "r": OPEN_EXISTING, 
    "w": OPEN_ALWAYS, 
    "r+": OPEN_ALWAYS, 
} 


def open_file_nonblocking(filename, access): 
    # Removes the b for binary access. 
    internal_access = access.replace("b", "") 
    access_mode = ACCESS_MODES[internal_access] 
    open_mode = OPEN_MODES[internal_access] 
    handle = wintypes.HANDLE(ctypes.windll.kernel32.CreateFileW(
     wintypes.LPWSTR(filename), 
     wintypes.DWORD(access_mode), 
     wintypes.DWORD(2|1), # File share read and write 
     ctypes.c_void_p(0), 
     wintypes.DWORD(open_mode), 
     wintypes.DWORD(0), 
     wintypes.HANDLE(0) 
    )) 

    try: 
     fd = msvcrt.open_osfhandle(handle.value, 0) 
    except OverflowError as exc: 
     # Python 3.X 
     raise OSError("Failed to open file.") from None 
     # Python 2 
     # raise OSError("Failed to open file.") 

    return os.fdopen(fd, access) 

関数は、ファイルを開きます。その後、ハンドルを通常のPythonファイルオブジェクトに変換します。
終了したら、ファイルを閉じてください。

0

最近、私はstdinでI/O読み取りを行う必要がありました。クロスプラットフォーム互換性を備えたPythonでstdoutしました。
Linuxの場合
Linuxの場合selectモジュールを使用できます。 posix selectのラッパー実装です。複数のファイル記述子を渡して、準備が整うのを待ちます。彼らが準備ができたら通知され、read/writeアクションが実行できます。ここでは、ここであなたのアイデア
をnodejs取得します少しのコードでは、このコード例は、関与標準入力、標準出力で操作を読み書きしている両方nodejs画像とのドッキングウィンドウ環境ウィンドウ については

stdin_buf = BytesIO(json.dumps(fn) + "\n") 
    stdout_buf = BytesIO() 
    stderr_buf = BytesIO() 

    rselect = [nodejs.stdout, nodejs.stderr] # type: List[BytesIO] 
    wselect = [nodejs.stdin] # type: List[BytesIO] 
    while (len(wselect) + len(rselect)) > 0: 
      rready, wready, _ = select.select(rselect, wselect, []) 
      try: 
       if nodejs.stdin in wready: 
        b = stdin_buf.read(select.PIPE_BUF) 
        if b: 
         os.write(nodejs.stdin.fileno(), b) 
        else: 
         wselect = [] 
       for pipes in ((nodejs.stdout, stdout_buf), (nodejs.stderr, stderr_buf)): 
        if pipes[0] in rready: 
         b = os.read(pipes[0].fileno(), select.PIPE_BUF) 
         if b: 
          pipes[1].write(b) 
         else: 
          rselect.remove(pipes[0]) 
       if stdout_buf.getvalue().endswith("\n"): 
        rselect = [] 
      except OSError as e: 
       break 

です。 Windowsでは、implelentationがstdinを許可しないので、stdoutが引数として渡されるため、このコードはWindows OSでは機能しません。
ドキュメントは言う:Windows上

Fileオブジェクトが許容可能ではないですが、ソケットです。 Windowsでは、基本となるselect()関数はWinSockライブラリによって提供され、WinSockからのものではないファイル記述子は処理しません。

まず私は、ライブラリの多くは、I/Oは、(のpython 2.7用)asyncio(のpython 3)、geventなどの窓に読ん非ブロックのためにそこにあることを言及する必要があり、msvcrt、その後pywin32さんがあるwin32eventことあなたのソケットがread/writeデータの準備ができている場合に警告します。しかし、それらのどれもが
など
An operation is performend on something that is not a socket
Handles only expect integer valuesように私はstdin/stdout与えerrrosに書き込みを読み取ることができません、私は試していないtwisterのようないくつかの他のライブラリがあります。

Windowsプラットフォームで上記のコードのような機能を実装するには、threadsを使用しました。ここに私のコードです:

stdin_buf = BytesIO(json.dumps(fn) + "\n") 
    stdout_buf = BytesIO() 
    stderr_buf = BytesIO() 

    rselect = [nodejs.stdout, nodejs.stderr] # type: List[BytesIO] 
    wselect = [nodejs.stdin] # type: List[BytesIO] 
    READ_BYTES_SIZE = 512 

    # creating queue for reading from a thread to queue 
    input_queue = Queue.Queue() 
    output_queue = Queue.Queue() 
    error_queue = Queue.Queue() 

    # To tell threads that output has ended and threads can safely exit 
    no_more_output = threading.Lock() 
    no_more_output.acquire() 
    no_more_error = threading.Lock() 
    no_more_error.acquire() 

    # put constructed command to input queue which then will be passed to nodejs's stdin 
    def put_input(input_queue): 
     while True: 
      sys.stdout.flush() 
      b = stdin_buf.read(READ_BYTES_SIZE) 
      if b: 
       input_queue.put(b) 
      else: 
       break 

    # get the output from nodejs's stdout and continue till otuput ends 
    def get_output(output_queue): 
     while not no_more_output.acquire(False): 
      b=os.read(nodejs.stdout.fileno(), READ_BYTES_SIZE) 
      if b: 
       output_queue.put(b) 

    # get the output from nodejs's stderr and continue till error output ends 
    def get_error(error_queue): 
     while not no_more_error.acquire(False): 
      b = os.read(nodejs.stderr.fileno(), READ_BYTES_SIZE) 
      if b: 
       error_queue.put(b) 

    # Threads managing nodejs.stdin, nodejs.stdout and nodejs.stderr respectively 
    input_thread = threading.Thread(target=put_input, args=(input_queue,)) 
    input_thread.start() 
    output_thread = threading.Thread(target=get_output, args=(output_queue,)) 
    output_thread.start() 
    error_thread = threading.Thread(target=get_error, args=(error_queue,)) 
    error_thread.start() 

    # mark if output/error is ready 
    output_ready=False 
    error_ready=False 

    while (len(wselect) + len(rselect)) > 0: 
     try: 
      if nodejs.stdin in wselect: 
       if not input_queue.empty(): 
        os.write(nodejs.stdin.fileno(), input_queue.get()) 
       elif not input_thread.is_alive(): 
        wselect = [] 
      if nodejs.stdout in rselect: 
       if not output_queue.empty(): 
        output_ready = True 
        stdout_buf.write(output_queue.get()) 
       elif output_ready: 
        rselect = [] 
        no_more_output.release() 
        no_more_error.release() 
        output_thread.join() 

      if nodejs.stderr in rselect: 
       if not error_queue.empty(): 
        error_ready = True 
        stderr_buf.write(error_queue.get()) 
       elif error_ready: 
        rselect = [] 
        no_more_output.release() 
        no_more_error.release() 
        output_thread.join() 
        error_thread.join() 
      if stdout_buf.getvalue().endswith("\n"): 
       rselect = [] 
       no_more_output.release() 
       no_more_error.release() 
       output_thread.join() 
     except OSError as e: 
      break 

私にとって最良の選択肢はスレッドであることが判明しました。あなたがもっと知りたい場合、この記事はnice readになります。

関連する問題