2015-07-20 36 views
1

我试图用HTTPoison编写一个网页抓取工具。作为第一步,我沿着下面的步骤写了一个简短的HTTP访问代码;Elixir:如何正确描述mix.exs设置?

  1. 通过混合

    创建一个项目$混用新httptest1

  2. 撰写的lib/httptest1.ex短代码。

    defmodule Httptest1 do 
        require HTTPoison 
    
        def test1 do 
        ret = HTTPoison.get! "http://www.yahoo.com" 
        %HTTPoison.Response{status_code: 200, body: body} = ret 
        IO.inspect body 
        end 
    end 
    
    Httptest1.test1() 
    
  3. 修改mix.exs为HTTPoison。

    defmodule Httptest1.Mixfile do 
        use Mix.Project 
    
        def project do 
        [app: :httptest1, 
        version: "0.0.1", 
        elixir: "~> 1.0", 
        build_embedded: Mix.env == :prod, 
        start_permanent: Mix.env == :prod, 
        deps: deps] 
        end 
    
        # Configuration for the OTP application 
        def application do 
        [applications: [:logger, :httpoison]] 
        end 
    
        # Dependencies can be Hex packages: 
        # 
        defp deps do 
        [ 
        {:httpoison, "~> 0.6"} 
        ] 
        end 
    end 
    
  4. 运行$ mix deps.get的依赖关系。

  5. 运行$ mix run,则编译失败;

    ==> idna (compile) 
    Compiled src/idna.erl 
    Compiled src/idna_ucs.erl 
    Compiled src/punycode.erl 
    (... snip ...) 
    Generated httpoison app 
    
    == Compilation error on file lib/httptest1.ex == 
    ** (exit) exited in: :gen_server.call(:hackney_manager, {:new_request, #PID<0.154.0>, #Reference<0.0.1.1724>, {:client, :undefined, :hackney_dummy_metrics, :hackney_tcp_transport, 'www.yahoo.com', 80, "www.yahoo.com", [connect_timeout: 5000, recv_timeout: :infinity], nil, nil, nil, true, :hackney_pool, :infinity, false, 5, false, 5, nil, nil, nil, :undefined, :start, nil, :normal, false, false, false, false, nil, :waiting, nil, 4096, "", [], :undefined, nil, nil, nil, nil, :undefined, nil}}, :infinity) 
        ** (EXIT) no process 
        (stdlib) gen_server.erl:212: :gen_server.call/3 
        src/hackney_client/hackney_manager.erl:66: :hackney_manager.init_request/1 
        src/hackney_client/hackney_manager.erl:56: :hackney_manager.new_request/1 
        src/hackney_connect/hackney_connect.erl:181: :hackney_connect.socket_from_pool/4 
        src/hackney_connect/hackney_connect.erl:36: :hackney_connect.connect/5 
        src/hackney_client/hackney.erl:319: :hackney.request/5 
        lib/httpoison.ex:60: HTTPoison.request/5 
        lib/httpoison.ex:60: HTTPoison.request!/5 
    

当我使用$ iex -S mix代替,其结果是一样的。

但是,如果我将httptest1.ex移动到放置mix.exs的相同目录中,如$ mv lib/httptest1.ex .,并试图明确指定源文件;它工作正常。

问题: 我怀疑我的mix.exs设置出了问题,那是什么?

+0

我有类似的错误信息。该代码在IEX中正确执行且没有错误,但在运行混合任务时会引发错误。为我工作的解决方案是“HTTPoison.start”也许这有助于在另一种情况下出现类似错误消息的人。 –

回答

2

全部.exlib/被编译。由于Elixir是编译文件时的元编程语言,因此您实际上正在运行代码。这意味着编译项目时会执行Httptest1.test1()

HTTPoison需要启动才能正常工作。它是在您的应用程序启动时启动的,当您执行mix run ...时。但是当你的项目正在编译你的项目,或者你的依赖没有启动,因此对你的依赖关系的调用可能会失败。

查看本章Supervisor and Application的入门指南,了解如何在应用程序启动时运行代码。

+0

谢谢。至少我发现只需从我的代码中省略Httptest1.test1(),然后手动启动$ iex -S mix和Httptest1.test1即可。我的另一个问题是,为什么指定的.ex文件直接在没有放在./lib时工作。 – HirofumiTamori

+0

因为它不会与您的项目一起编译。它运行(并编译),当你做'混合运行...',这将使你的HTTPoison已经启动并运行。 –

+0

换句话说,'$ mix run httptest1.ex'编译lib和依赖模块下的文件,但只在HTTPoison启动后运行./httptest1.ex,它是正确的吗? – HirofumiTamori

0

改进!现在我知道如何创建一个可执行的调用命令行。

程序;

defmodule Httptest1 do 
    use Application 
    require HTTPoison 

    def start(_type, _args) do 
    import Supervisor.Spec, warn: false 
    children = [] 
    opts = [strategy: :one_for_one, name: Httptest1.Supervisor] 
    Supervisor.start_link(children, opts) 
    end 

    def main(args) do # entry point 
    ret = HTTPoison.get! "http://www.yahoo.com" 
    %HTTPoison.Response{status_code: _, body: body} = ret # no status code matching now 
    IO.inspect body 
    end 

end 

和mix.exs(均由$ mix new httptest1 --sup supervisor选项创建);

Httptest.test1 $ iex -S mix类型调用IEX
defmodule Httptest1.Mixfile do 
    use Mix.Project 

    def project do 
    [app: :httptest1, 
    version: "0.0.1", 
    elixir: "~> 1.0", 
    build_embedded: Mix.env == :prod, 
    start_permanent: Mix.env == :prod, 
    escript: escript, # <<<< Added 
    deps: deps] 
    end 

    def escript do # define escript 
    [main_module: Httptest1] 
    end 

    def application do 
    [applications: [:logger, :httpoison], 
    mod: {Httptest1, []}] # 
    end 

    defp deps do 
    [ 
     {:httpoison, "~> 0.6"} 
    ] 
    end 
end 

然后,预期的结果登场!谢谢。

此外,为了创建命令行可执行,

$ mix escript.build 

则产生./httptest1。完成。